Compare commits

...
113 Commits
Author SHA1 Message Date
Robert Brennan e9bf38fe28 Update triage.yml 2022-08-09 13:00:27 -04:00
Robert Brennan 4601c1fff4 Update triage.yml 2022-08-09 12:46:03 -04:00
Robert Brennan e81c2d3930 Update triage.yml 2022-08-09 12:42:52 -04:00
Robert Brennan 9f33a603e4 Update triage.yml 2022-08-09 12:42:07 -04:00
Robert Brennan 7bae85c493 Update triage.yml 2022-08-09 12:37:55 -04:00
Robert Brennan 468bc2ef64 Update triage.yml 2022-08-09 12:30:48 -04:00
Robert Brennan ab2d52b8d8 Update triage.yml 2022-08-09 12:21:36 -04:00
Robert Brennan b079665364 Update triage.yml 2022-08-09 12:20:31 -04:00
Robert Brennan baad393ea5 Update triage.yml 2022-08-09 12:17:28 -04:00
Robert Brennan 025cac8981 Update triage.yml 2022-08-09 12:15:09 -04:00
Robert Brennan f229f4d663 Update triage.yml 2022-08-09 12:09:33 -04:00
Robert Brennan e1cbe4ce6a Update triage.yml 2022-08-09 12:00:22 -04:00
Robert Brennan 5d91a5f7e0 Update triage.yml 2022-08-09 11:54:00 -04:00
Robert Brennan c5ac49583e Update triage.yml 2022-08-09 11:52:13 -04:00
Robert Brennan 8ff5ad679a Update triage.yml 2022-08-09 11:51:25 -04:00
Robert Brennan c09dac5262 Update triage.yml 2022-08-09 11:49:52 -04:00
Robert Brennan 7c675c6d43 Update triage.yml 2022-08-09 11:40:50 -04:00
Robert Brennan 6ef6193c3d Update triage.yml 2022-08-09 10:35:25 -04:00
Robert Brennan bd9dd660ff Update triage.yml 2022-08-09 10:35:14 -04:00
Robert Brennan 559736b1b2 Update triage.yml 2022-08-09 10:33:51 -04:00
Robert Brennan ef4b6ece30 Update triage.yml 2022-08-09 10:32:34 -04:00
Robert Brennan 34152609a8 Update triage.yml 2022-08-09 10:27:00 -04:00
Robert Brennan 0879f2a040 Update triage.yml 2022-08-09 10:22:17 -04:00
Robert Brennan a2123293f7 Update triage.yml 2022-08-09 10:19:42 -04:00
Robert Brennan a5acc96001 Update triage.yml 2022-08-09 10:17:22 -04:00
Robert Brennan e2e7918d36 Update triage.yml 2022-08-09 10:10:22 -04:00
Robert Brennan ad7b4f6aee Update triage.yml 2022-08-09 10:03:27 -04:00
Robert Brennan 581d06c194 Update triage.yml 2022-08-09 10:02:25 -04:00
Robert Brennan 729e7a9482 Update triage.yml 2022-08-09 10:01:01 -04:00
Robert Brennan a63756a158 Update triage.yml 2022-08-09 09:58:15 -04:00
Robert Brennan affab91d92 Update triage.yml 2022-08-09 09:55:28 -04:00
Robert Brennan ccd707f230 Update triage.yml 2022-08-09 09:53:17 -04:00
Robert Brennan 68064da185 Update triage.yml 2022-08-09 09:52:46 -04:00
Robert Brennan e4758dbc44 Update triage.yml 2022-08-09 09:50:20 -04:00
Robert Brennan 09209c9a7b Update triage.yml 2022-08-09 09:48:45 -04:00
Robert Brennan 8a7e691a8e Update triage.yml 2022-08-09 09:39:34 -04:00
Robert Brennan 3440296557 Update triage.yml 2022-08-09 09:37:04 -04:00
Robert Brennan 511157e010 Update triage.yml 2022-08-09 09:36:15 -04:00
Robert Brennan 195b9a8860 Update triage.yml 2022-08-09 09:35:41 -04:00
Robert Brennan 93b251d5c0 Update triage.yml 2022-08-09 09:33:40 -04:00
Robert Brennan af840db564 Update triage.yml 2022-08-09 09:32:30 -04:00
Robert Brennan 909bc5e86b Update triage.yml 2022-08-09 09:29:33 -04:00
Robert Brennan 3cdaf143a4 Update triage.yml 2022-08-09 09:27:50 -04:00
Robert Brennan 693dbc5b25 Update triage.yml 2022-08-09 09:03:02 -04:00
Robert Brennan b77672bde8 Update triage.yml 2022-08-08 18:14:48 -04:00
Robert Brennan bf96f1dc89 Update triage.yml 2022-08-08 18:07:50 -04:00
Robert Brennan 40c6c569e0 Update triage.yml 2022-08-08 16:05:11 -04:00
Robert Brennan fe014ac2bf Update triage.yml 2022-08-08 16:04:18 -04:00
Robert Brennan 5f87baaa56 Update triage.yml 2022-08-08 16:01:53 -04:00
Robert Brennan 35e7896553 Update triage.yml 2022-08-08 15:55:39 -04:00
Robert Brennan 1d7d3433c1 Update triage.yml 2022-08-08 15:51:21 -04:00
Robert Brennan 3a421412bb Create triage.yml 2022-08-08 15:43:45 -04:00
ivanfetch-fw 206322271c FWI-2509: Add sensitiveContainerEnvVar and sensitiveConfigMapContent checks (#817)
* Add sensitiveContainerEnvVar and sensitiveConfigMapContent checks

* Update full example configfile
2022-08-05 11:58:57 -04:00
ivanfetch-fw e5b9236268 FWI-2476: Add missingNetworkPolicy, automountServiceAccountToken, and linuxHardening checks (#816)
* Add missingNetworkPolicy, automountServiceAccountToken, and linuxHardening checks
2022-08-05 09:44:18 -06:00
ivanfetch-fw c3b57bf6c7 target: container also populates .Polaris.PodSpec|PodTemplate + a new .Polaris.Container representing the currently checked container, GetPodTemplate serializes data to work around a DeepCopy bug with type int (#812) 2022-07-29 07:45:56 -06:00
Igor BeliakovandRobert Brennan 652b65b3c2 fix: properly remove emojis in pretty format with no color (#765)
Signed-off-by: Igor Beliakov <demtis.register@gmail.com>

Co-authored-by: Robert Brennan <accounts@rbren.io>
2022-07-28 15:39:17 -04:00
dependabot[bot]andlnx01 41030320bb Bump github.com/stretchr/testify from 1.7.1 to 1.8.0 (#786)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.7.1 to 1.8.0.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.7.1...v1.8.0)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-28 15:30:09 -04:00
dependabot[bot]andlnx01 76c42c4799 Bump github.com/spf13/cobra from 1.4.0 to 1.5.0 (#813)
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.4.0 to 1.5.0.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Commits](https://github.com/spf13/cobra/compare/v1.4.0...v1.5.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-28 15:29:58 -04:00
65add73e70 Bump k8s.io/api from 0.24.1 to 0.24.3 (#808)
Bumps [k8s.io/api](https://github.com/kubernetes/api) from 0.24.1 to 0.24.3.
- [Release notes](https://github.com/kubernetes/api/releases)
- [Commits](https://github.com/kubernetes/api/compare/v0.24.1...v0.24.3)

---
updated-dependencies:
- dependency-name: k8s.io/api
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Barnabas Makonda <6409210+makoscafee@users.noreply.github.com>
2022-07-28 15:21:50 -04:00
Igor BeliakovandRobert Brennan a0000e1919 Suppress empty results when --only-show-failed-tests is passed (#811)
* Suppress empty results when --only-show-failed-tests is passed

Signed-off-by: Igor Beliakov <demtis.register@gmail.com>

* Fix remaining typo

Signed-off-by: Igor Beliakov <demtis.register@gmail.com>

Co-authored-by: Robert Brennan <accounts@rbren.io>
2022-07-26 09:31:08 -04:00
dependabot[bot]andlnx01 f9e2603b16 Bump alpine from 3.16.0 to 3.16.1 (#810)
Bumps alpine from 3.16.0 to 3.16.1.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-07-25 17:21:08 +03:00
ivanfetch-fw 50d789fd42 Fix resourceKindMap.addResource() to not assume every Kind has an APIGroup (#805)
This was causing the `ResourceProvider.Resources` map to essentially
loose resources with no APIGroup, such as ServiceAccounts.
2022-07-15 13:53:41 -06:00
ivanfetch-fwandRobert Brennan 25ab600eef Update docs to reflect target: PodTemplate RE: PR #801 (#804)
* Update docs to reflect `target: PodTemplate` and the template being available via the `Polaris.PodTemplate` variable RE: PR #801

* Fix typo

Co-authored-by: Robert Brennan <accounts@rbren.io>

Co-authored-by: Robert Brennan <accounts@rbren.io>
2022-07-14 13:50:41 -06:00
ivanfetch-fw be45519a22 Add target PodTemplate which exposes the full Pod (not only the spec) (#801)
* Add `target PodTemplate` which exposes the full Pod (not only the spec)

* Fix PotTemplate in conjunction with how pod-schema-checks are handled

* Add test for GO template `Polaris` sub-keys, help `NewGenericResourceFromPod` to set `PodTemplate` in more cases

* Clarify PldTemplate logic for `IsActionable()`
2022-07-14 12:51:24 -06:00
ivanfetch-fw ccaa384cd0 expose Polaris.PodSpec for PodSpec targeted checks (#793)
* Add a template `Polaris` variable, expose `Polaris.PodSpec` for checks of `target: PodSpec`.

Polaris checks that are `target: PodSpec` have reflected the original
resource (such as a pod-controller) in the Go template, instead of
reflecting the pod `spec` field. This update makes the PodSpec available
in a new template variable `Polaris.PodSpec`.
2022-07-12 08:04:17 -06:00
Robert Brennan 1c09ce9e09 update changelog and docs (#800)
* update changelog and docs

* add 7.0.1

* fix version
2022-07-11 14:12:50 -04:00
Robert Brennan fec00893b1 Update fairwinds-insights.yaml (#799) 2022-07-11 14:06:58 -04:00
Robert Brennan acadebe9fd add docs for mutation (#792)
* add docs for mutation

* Update infrastructure-as-code.md
2022-07-11 13:25:15 -04:00
Robert Brennan a2ec025230 Add more mutations, fix mutation tests (#790)
* add more mutations

* fix tests

* add more test cases

* Update insecureCapabilities.yaml

* Update dangerousCapabilities.yaml

* fix tests

* fix tests
2022-07-11 13:22:14 -04:00
Robert Brennan 08682075c6 Enable pullPolicyNotAlways (#795)
* add more mutations

* fix tests

* add more test cases

* Update insecureCapabilities.yaml

* Update dangerousCapabilities.yaml

* fix tests

* fix tests

* add pullPolicyNotAlways as default mutation
2022-07-11 13:20:17 -04:00
Barnabas MakondaandRobert Brennan e3e790046f Add checks flag to fix specific checks (#797)
* add checks to fix  and fix-all-checks flags

* only use one flag

* add example

Co-authored-by: Robert Brennan <accounts@rbren.io>
2022-07-11 11:12:08 -06:00
Robert Brennan 50319fb1b8 fix webhook test (#798)
* add logs to webhook test

* fix cleanup

* add more logs

* fix webhhook test
2022-07-11 13:06:21 -04:00
Robert Brennan c3eb0811e0 Add flag to enable mutations in webhook (#794)
* rb/mutation-flag

* add validate flag
2022-07-11 09:37:54 -04:00
Andrew Suderman 5423449177 Use orb to publish docs (#791)
* Use orb to publish docs

* copy/pasta

* remove test values

* typo
2022-07-07 11:52:12 -06:00
Robert Brennan f713d43697 ensure path exists when adding mutations (#789) 2022-07-07 10:00:36 -04:00
Barnabas Makonda e896eec89f Expose GetValidateResults function to be used in the polaris package (#763)
* Expose GetValidateResults function to be used in the polaris package

* change to GetValidatedResults
2022-06-15 15:28:33 +03:00
Barnabas Makonda 25a120ba65 update dependencies (#777) 2022-06-07 20:27:26 +03:00
3b865fcea8 skip incomplete or broken YAML - warn user (#678)
* skip broken yaml (eg, patch file)

* skip in visitFile, not in parser

* restore filepath.Walk() error handling

* restore test; correct assertion

* Update pkg/kube/resources_test.go

Co-authored-by: Robert Brennan <accounts@rbren.io>

* Fix tests

* update kind

Co-authored-by: Robert Brennan <accounts@rbren.io>
Co-authored-by: Luke Reed <luke@lreed.net>
Co-authored-by: Barnabas Makonda <6409210+makoscafee@users.noreply.github.com>
Co-authored-by: MAKOSCAFEE <barnabasmakonda@gmail.com>
2022-06-07 12:02:27 -04:00
Robert BrennanandMAKOSCAFEE f71ca999c9 Change target: Pod to target: PodSpec (#726)
* change target pod to target pod spec

* add checks

* update docs

* fix tests

Co-authored-by: MAKOSCAFEE <barnabasmakonda@gmail.com>
2022-06-07 07:37:25 -06:00
dependabot[bot]andlnx01 276c168839 Bump alpine from 3.15.4 to 3.16.0 (#773)
Bumps alpine from 3.15.4 to 3.16.0.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-06-01 23:02:14 +03:00
Barnabas Makonda 92f0b6e551 fix issue when the files-path is actual file path instead of directory (#761)
* fix issue when the files-path is actual path

* remove check for file extension

* do not panic when sub command is not there

* remove panic and fail graciously
2022-05-12 07:45:46 -06:00
Barnabas Makonda 6b7d6ab301 Added Mutation webhook (#755)
* added mutate webhook

* fix mutation operation type

* if no mutation just use valid response
2022-05-03 17:42:19 +03:00
Robert BrennanandBarnabas Makonda 6c33168378 update release process (#744)
* update release process

* fix lint

* remove kubectl docs

* update webhook install

* fix webhook_test

* fix dashboard test

* Update kube_dashboard_test.sh

* Update webhook_test.sh

Co-authored-by: Barnabas Makonda <6409210+makoscafee@users.noreply.github.com>
2022-04-28 17:16:17 -04:00
8a8ac2d9b9 update go modules (#743)
* update go modules

* go 1.18

* git mod tidy

* go mod tidy again

Co-authored-by: MAKOSCAFEE <barnabasmakonda@gmail.com>
Co-authored-by: Barnabas Makonda <6409210+makoscafee@users.noreply.github.com>
2022-04-28 23:18:38 +03:00
Barnabas Makonda a59063bdb2 Add fix command to mutate and update IaC (#746)
* added fix command

* update fix command to walk through the folder to find all files

* added ability to add comment

* fix comment prefix

* trim whitespaces to the line

* refactor update mutated file

* remove filepath as is not needed anymore

* remove filepath as is not needed anymore

* remove timestamp and status if creation is null

* added comments and fix tests

* remove hardcoded mutation in config

* revert comment deletion

* separate mutated to success files

* read multiple resources in a file and update both

* Remove mutation in config.yaml
2022-04-28 18:28:33 +03:00
Terraform User c597b162d9 Managed by Terraform 2022-04-26 13:31:39 -06:00
Robert Brennan 322e6f7dcd fix kinds (#752) 2022-04-25 11:52:38 -04:00
Robert Brennan c92819ca9d Save last podspec when walking owner hierarchy (#748)
* try saving last podspec when walking owner hierarchy

* remove namespace from config
2022-04-25 11:09:22 -04:00
dependabot[bot]andlnx01 57d0ae3932 Bump alpine from 3.15.3 to 3.15.4 (#745)
Bumps alpine from 3.15.3 to 3.15.4.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-12 15:47:27 +03:00
Barnabas MakondaandRobert Brennan 321bfa8f1f Added more mutations and refactor test to test each mutation separately (#734)
* added more mutations and refactor test to test each mutation separately

* added more mutation definitions

* update spec for controller

* added mutations for cpu and memory request and limits

* update request memory mutation

* added liveness and probes

* rmeove hostport mutation

* added multiple mutations for request and limits memory

Co-authored-by: Robert Brennan <accounts@rbren.io>
2022-04-08 17:19:14 +03:00
Andrew Suderman 78838a606d Add a --namespace flag to the in-cluster audit (#742) 2022-04-08 07:54:03 -06:00
staerionandRobert Brennan fd16fb993d merge the list of resources from custom checks and the generated controller list before deduplicating them (#727)
Co-authored-by: Robert Brennan <accounts@rbren.io>
2022-04-07 10:18:04 -04:00
Ken KaizuandRobert Brennan 1841b7441d audit check specific checks when passing checks args (#737)
Signed-off-by: krrrr38 <k.kaizu38@gmail.com>

Co-authored-by: Robert Brennan <accounts@rbren.io>
2022-04-07 09:11:51 -04:00
Robert Brennan ce8786b9d2 update x/text (#740) 2022-04-07 09:10:57 -04:00
dependabot[bot]andlnx01 82d366364f Bump alpine from 3.15.2 to 3.15.3 (#739)
Bumps alpine from 3.15.2 to 3.15.3.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-04-05 16:20:34 +03:00
Andrew SudermanandBarnabas Makonda bd8b2962dc Fix license headers (#736)
* Update license headers

* Fmt

Co-authored-by: Barnabas Makonda <6409210+makoscafee@users.noreply.github.com>
2022-03-31 11:02:10 -04:00
dependabot[bot]andlnx01 f2833f2c4e Bump alpine from 3.15.1 to 3.15.2 (#733)
Bumps alpine from 3.15.1 to 3.15.2.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-29 15:02:45 -04:00
Barnabas Makonda a4c0b0f555 Add mutation field to imagePolicyNotAlways (#712)
* added mutation field in checks and config

* added test

* fix tests

* revert resolve export

* remove Patched resources as moving that to separate functionality apart from validation

* go mod tidy

* move mutation to the container level

* change prefix based on the resource kind

* collect all mutations from results and apply

* added test for cronjob and deployment apart from just pod

* test cronjob prefix

* return a copy of mutation

* fix tests and comments

* address feedback comments

* fix warning formating

* refactor getJSONSchemaPrefix function
2022-03-25 16:38:58 +03:00
dependabot[bot]andlnx01 a7e30075a9 Bump alpine from 3.15.0 to 3.15.1 (#731)
Bumps alpine from 3.15.0 to 3.15.1.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-03-24 11:08:56 -04:00
861fd42d29 Bump golang from 1.17.7 to 1.17.8 (#716)
* Bump golang from 1.17.7 to 1.17.8

Bumps golang from 1.17.7 to 1.17.8.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update Dockerfile

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Robert Brennan <accounts@rbren.io>
2022-03-17 09:54:31 -04:00
Robert BrennanandTravis CI ef50fbbff6 Release 5.1 (#720)
* bump to 5.1.0

* regenerate deploy files

Co-authored-by: Travis CI <jess.portnoy@kaltura.com>
2022-03-15 10:02:20 -04:00
nobletrout f429f1922a Nobletrout/add kubectx support (#719)
* See #699 add support for kubecontext selection

* Update cli.md
2022-03-15 09:24:24 -04:00
nobletrout 06322dc8a4 bounce out once we hit a type we know to avoid CRD problems (#718) 2022-03-14 16:41:43 -04:00
Terraform User afe718b621 Managed by Terraform 2022-03-04 10:56:22 -07:00
dependabot[bot]andlnx01 5e4d6bd857 Bump github.com/spf13/cobra from 1.2.1 to 1.3.0 (#687)
Bumps [github.com/spf13/cobra](https://github.com/spf13/cobra) from 1.2.1 to 1.3.0.
- [Release notes](https://github.com/spf13/cobra/releases)
- [Changelog](https://github.com/spf13/cobra/blob/master/CHANGELOG.md)
- [Commits](https://github.com/spf13/cobra/compare/v1.2.1...v1.3.0)

---
updated-dependencies:
- dependency-name: github.com/spf13/cobra
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-23 16:26:38 -05:00
dependabot[bot]andlnx01 e61c50a6a1 Bump golang from 1.16 to 1.17.7 (#705)
Bumps golang from 1.16 to 1.17.7.

---
updated-dependencies:
- dependency-name: golang
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-23 16:26:14 -05:00
dependabot[bot]andlnx01 b1e22ab47b Bump alpine from 3.14 to 3.15.0 (#704)
Bumps alpine from 3.14 to 3.15.0.

---
updated-dependencies:
- dependency-name: alpine
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-02-23 16:26:04 -05:00
Andrew Suderman 986d47b5dd CI/CD Updates - get publish secrets from vault. Update goreleaser. Sign checksums. Enable experimental docker features to move towards multi-arch support (#710) 2022-02-22 16:14:10 -07:00
Terraform User 8c18e40024 Managed by Terraform 2022-02-17 11:20:37 -07:00
Terraform User f79d0ee3ee Managed by Terraform 2022-02-17 11:20:35 -07:00
Andrew Suderman 539fa088d1 Update documentation from template (#702) 2022-02-15 14:43:07 -07:00
Luke Reed ab7bb94b39 Update goreleaser to v1.1.0 (#700) 2022-02-09 08:14:14 -05:00
Luke Reed 2aedaa9ba4 Benchmark banner image (#696) 2022-01-27 14:20:40 -07:00
173 changed files with 3528 additions and 892 deletions
+40 -57
View File
@@ -1,5 +1,9 @@
version: 2.1
orbs:
rok8s: fairwinds/rok8s-scripts@11
oss-docs: fairwinds/oss-docs@0
executors:
vm:
machine:
@@ -18,6 +22,7 @@ references:
echo 'export GOPROXY=https://proxy.golang.org' >> ${BASH_ENV}
echo 'export GO111MODULE=on' >> ${BASH_ENV}
echo 'export GOFLAGS=-mod=mod' >> ${BASH_ENV}
echo 'export GORELEASER_CURRENT_TAG="${CIRCLE_TAG}"' >> $BASH_ENV
install_k8s: &install_k8s
run:
@@ -28,20 +33,20 @@ references:
sudo apt-get install -yqq jq git
echo "Installing KIND"
curl -sLO https://github.com/kubernetes-sigs/kind/releases/download/v0.8.1/kind-linux-amd64
curl -sLO https://github.com/kubernetes-sigs/kind/releases/download/v0.14.0/kind-linux-amd64
chmod 0755 kind-linux-amd64
sudo mv kind-linux-amd64 /usr/local/bin/kind
kind version
echo "Installing Kubectl"
curl -sLO https://storage.googleapis.com/kubernetes-release/release/v1.18.6/bin/linux/amd64/kubectl
curl -sLO https://storage.googleapis.com/kubernetes-release/release/v1.21.12/bin/linux/amd64/kubectl
chmod 0755 kubectl
sudo mv kubectl /usr/local/bin/
kubectl version --client
echo "Creating Kubernetes Cluster with Kind"
kind create cluster --wait=90s --image kindest/node:v1.15.11
kind create cluster --wait=90s --image kindest/node:v1.21.12
docker ps -a
kubectl version
@@ -82,16 +87,6 @@ references:
echo "Skipping Kubernetes tests for forked PR"
fi
# Release scripts
install_goreleaser: &install_goreleaser
run:
name: Install GoReleaser
command: |
curl -fsSLo goreleaser.deb https://github.com/goreleaser/goreleaser/releases/download/v0.174.2/goreleaser_amd64.deb
echo "bad33997ea9977a84196bdca1d5993fada909cd81c3e88d52bd297666bea61a4 goreleaser.deb" | sha256sum -c -
sudo dpkg -i goreleaser.deb
rm goreleaser.deb
docker_build: &docker_build
run:
name: Docker login and build
@@ -108,14 +103,25 @@ references:
docker login quay.io -u="${fairwinds_quay_user}" -p="${fairwinds_quay_token}"
docker-push -f .circleci/build.config
release_deploy_configs: &release_deploy_configs
enable_experimental_features: &enable_experimental_docker_features
run:
name: Release deploy configs
name: enable experimental features
command: |
upload_url=$(curl --silent https://api.github.com/repos/FairwindsOps/polaris/releases/latest | grep upload_url)
upload_url=$(echo $upload_url | sed -e 's/.*\(https.*\){.*$/\1/')
curl -X POST "$upload_url?name=dashboard.yaml" --data-binary "@./deploy/dashboard.yaml" -H "Authorization: Bearer $GITHUB_TOKEN" -H "Content-Type: application/x-yaml"
curl -X POST "$upload_url?name=webhook.yaml" --data-binary "@./deploy/webhook.yaml" -H "Authorization: Bearer $GITHUB_TOKEN" -H "Content-Type: application/x-yaml"
set -ex
apk --update add openssh
ssh remote-docker \<<EOF
sudo bash -c 'echo "{\"experimental\": true}" > /etc/docker/daemon.json'
sudo systemctl restart docker
EOF
install_vault_alpine: &install_vault_alpine
run:
name: install hashicorp vault
command: |
apk --update add curl yq
cd /tmp
curl -LO https://releases.hashicorp.com/vault/1.9.3/vault_1.9.3_linux_amd64.zip
unzip vault_1.9.3_linux_amd64.zip
mv vault /usr/bin/vault
jobs:
build:
@@ -148,7 +154,7 @@ jobs:
test:
working_directory: /go/src/github.com/fairwindsops/polaris/
docker:
- image: circleci/golang:1.16
- image: circleci/golang:1.17
steps:
- checkout
- *set_environment_variables
@@ -156,7 +162,6 @@ jobs:
- run: go list ./... | grep -v vendor | xargs golint -set_exit_status
- run: go list ./... | grep -v vendor | xargs go vet
- run: go test ./... -coverprofile=coverage.txt -covermode=count
- run: go run main.go audit --audit-path ./deploy --set-exit-code-below-score 100 --set-exit-code-on-danger
- *test_binary_dashboard
insights:
@@ -165,29 +170,32 @@ jobs:
steps:
- checkout
- setup_remote_docker
- run:
name: Adjust configs for latest image
command: |
sed -r "s|'(quay.io/fairwinds/polaris:).+'|'\1${CIRCLE_SHA1}'|" ./deploy/webhook.yaml > ./deploy/dashboard.yaml
sed -r "s|'(quay.io/fairwinds/polaris:).+'|'\1${CIRCLE_SHA1}'|" ./deploy/dashboard.yaml > ./deploy/webhook.yaml
- run:
name: Insights CI
command: curl -L https://insights.fairwinds.com/v0/insights-ci.sh | bash
release_binary:
working_directory: /go/src/github.com/fairwindsops/polaris/
resource_class: large
shell: /bin/bash
docker:
- image: circleci/golang:1.16
- image: goreleaser/goreleaser:v1.3.0
steps:
- checkout
- setup_remote_docker
- setup_remote_docker:
version: 20.10.6
- *enable_experimental_docker_features
- *install_vault_alpine
- rok8s/get_vault_env:
vault_path: repo/global/env
- rok8s/get_vault_env:
vault_path: repo/polaris/env
- *set_environment_variables
- *install_goreleaser
- run: go get -u github.com/gobuffalo/packr/v2/packr2
- run: git checkout -- . # FIXME: the go get makes the directory dirty
- run: packr2
- run: echo 'export GORELEASER_CURRENT_TAG="${CIRCLE_TAG}"' >> $BASH_ENV
- run: goreleaser
- *release_deploy_configs
release_images:
working_directory: /go/src/github.com/fairwindsops/polaris/
@@ -198,32 +206,6 @@ jobs:
- setup_remote_docker
- *set_environment_variables
- *docker_build_and_push
publish_docs:
docker:
- image: cimg/node:15.5.1
steps:
- checkout
- run:
name: Build Docs Site
command: |
set -e
cd ./docs
npm install
npm run check-links
npm run build
- run:
name: Install AWS CLI
command: |
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
sudo ./aws/install
- run:
name: Publish Docs Site to S3
command: |
cd ./dist
aws s3 sync ./ s3://polaris.docs.fairwinds.com --delete
workflows:
version: 2
@@ -271,7 +253,8 @@ workflows:
ignore: /.*/
tags:
ignore: /^testing-.*/
- publish_docs:
- oss-docs/publish-docs:
repository: polaris
filters:
branches:
ignore: /.*/
+2 -2
View File
@@ -30,8 +30,8 @@ body:
- type: input
id: version
attributes:
label: version
description: The version of the tool that you are using.
label: Version
description: The version of the tool that you are using. If a helm chart, please share the name of the chart.
validations:
required: true
- type: checkboxes
+18 -42
View File
@@ -1,44 +1,20 @@
## DO NOT EDIT - Managed by Terraform
version: 2
updates:
- package-ecosystem: gomod
directory: "/"
schedule:
interval: weekly
time: "11:00"
ignore:
- dependency-name: cloud.google.com/go
versions:
- ">= 0.57.a, < 0.58"
- dependency-name: github.com/go-logr/logr
versions:
- ">= 0.2.a, < 0.3"
- dependency-name: github.com/go-logr/zapr
versions:
- ">= 0.2.a, < 0.3"
- dependency-name: github.com/googleapis/gnostic
versions:
- ">= 0.4.a, < 0.5"
- dependency-name: github.com/googleapis/gnostic
versions:
- ">= 0.5.a, < 0.6"
- dependency-name: github.com/qri-io/jsonschema
versions:
- ">= 0.2.a, < 0.3"
- dependency-name: k8s.io/api
versions:
- ">= 0.19.a, < 0.20"
- dependency-name: k8s.io/apimachinery
versions:
- ">= 0.19.a, < 0.20"
- dependency-name: k8s.io/client-go
versions:
- ">= 0.19.a, < 0.20"
- dependency-name: sigs.k8s.io/controller-runtime
versions:
- ">= 0.5.a, < 0.6"
- dependency-name: sigs.k8s.io/controller-runtime
versions:
- ">= 0.8.a, < 0.9"
- dependency-name: k8s.io/apimachinery
versions:
- 0.20.4
- package-ecosystem: "docker"
directory: "/"
schedule:
interval: "weekly"
- package-ecosystem: "npm"
directory: "/docs"
schedule:
interval: "weekly"
open-pull-requests-limit: 0
ignore:
- dependency-name: "*"
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"
+1 -1
View File
@@ -1,4 +1,4 @@
This PR fixes issue #
This PR fixes #
## Checklist
* [ ] I have signed the CLA
+98
View File
@@ -0,0 +1,98 @@
name: Triage issues
on:
schedule:
- cron: '0 16 * * Mon' # noon ET on Mondays
issues:
types:
- reopened
- opened
pull_request:
types:
- reopened
- opened
jobs:
notify:
if: github.actor!= 'dependabot[bot]'
runs-on: ubuntu-latest
steps:
- uses: octokit/request-action@v2.x
id: need_triage
with:
route: GET /repos/FairwindsOps/${{ github.event.repository.name }}/issues?labels=triage
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Scheduled Reminders
env:
TITLES: ${{ join(fromJSON(steps.need_triage.outputs.data).*.title, ';') }}
LINKS: ${{ join(fromJSON(steps.need_triage.outputs.data).*.html_url, ';') }}
run: |
echo "Scheduled reminder! ${TITLES}"
IFS=';' read -r -a titles <<< "$TITLES"
IFS=';' read -r -a links <<< "$LINKS"
message=""
for index in "${!links[@]}"; do
title=${titles[$index]}
link=${links[$index]}
echo "$index $title $link"
message="$message- <$link|$title>\\n"
done
echo "message: $message"
echo '{
"text": "Needs Triage",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "$message"
}
}
]
}' > body-template.json
export message=$(echo "${message}" | sed 's/"//g')
envsubst < body-template.json > body.json
cat body.json
curl -X POST "${{ secrets.SLACK_INCOMING_WEBHOOK }}" -H "Content-type: application/json" -d @./body.json
- name: Issue Notification
if: github.event.issue.title != ''
env:
TITLE: "${{ github.event.issue.title }}"
EVENT: github.event.pull_request.merged == true
LINK: "https://github.com/FairwindsOps/${{ github.event.repository.name }}/pulls/${{ github.event.issue.number }}"
run: |
echo '{
"text": "New Pull Request",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": ":issue: New Issue: <${LINK}|${TITLE}>"
}
}
]
}' > body-template.json
envsubst < body-template.json > body.json
curl -X POST "${{ secrets.SLACK_INCOMING_WEBHOOK }}" -H "Content-type: application/json" -d @./body.json
- name: PR Notification
if: github.event.pull_request.title != ''
env:
TITLE: "${{ github.event.pull_request.title }}"
LINK: "https://github.com/FairwindsOps/${{ github.event.repository.name }}/pulls/${{ github.event.pull_request.number }}"
run: |
echo '{
"text": "New Pull Request",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": ":pr: New Pull Request: <${LINK}|${TITLE}>"
}
}
]
}' > body-template.json
envsubst < body-template.json > body.json
curl -X POST "${{ secrets.SLACK_INCOMING_WEBHOOK }}" -H "Content-type: application/json" -d @./body.json
+1
View File
@@ -1,4 +1,5 @@
# Binaries for programs and plugins
.go-version
*.exe
*.exe~
*.dll
+14
View File
@@ -8,6 +8,8 @@ changelog:
- '^test:'
builds:
- id: polaris
ldflags:
- -X main.Version={{.Version}} -X main.Commit={{.Commit}} -s -w
env:
- CGO_ENABLED=0
- GO111MODULE=on
@@ -26,6 +28,18 @@ archives:
- id: polaris
builds: ["polaris"]
name_template: "{{ .ProjectName }}_{{ .Os }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}{{ if .Mips }}_{{ .Mips }}{{ end }}"
signs:
- cmd: cosign
args: ["sign-blob", "--key=hashivault://cosign", "-output-signature=${signature}", "${artifact}"]
artifacts: checksum
release:
prerelease: auto
footer: |
You can verify the signature of the checksums.txt file using [cosign](https://github.com/sigstore/cosign).
```
cosign verify-blob checksums.txt --signature=checksums.txt.sig --key https://artifacts.fairwinds.com/cosign.pub
```
brews:
- name: polaris
tap:
+24
View File
@@ -0,0 +1,24 @@
header:
license:
spdx-id: Apache-2.0
copyright-owner: 'FairwindsOps, Inc.'
content: |
// Copyright 2019 FairwindsOps Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
paths:
- '**/*.go'
comment: on-failure
dependency:
files:
- go.mod
+2 -2
View File
@@ -1,4 +1,4 @@
FROM golang:1.16 AS build-env
FROM golang:1.17 AS build-env
WORKDIR /go/src/github.com/fairwindsops/polaris/
ENV GO111MODULE=on
@@ -15,7 +15,7 @@ RUN go get -u github.com/gobuffalo/packr/v2/packr2
COPY . .
RUN packr2 build -a -o polaris *.go
FROM alpine:3.14
FROM alpine:3.16.1
WORKDIR /usr/local/bin
RUN apk --no-cache add ca-certificates
+2 -2
View File
@@ -2,8 +2,8 @@
<img src="https://polaris.docs.fairwinds.com/img/polaris-logo.png" alt="Polaris Logo">
<br>
<h3>Best Practices for Kubernetes Workload Configuration</h3>
<a href="https://github.com/FairwindsOps/polaris">
<img src="https://img.shields.io/static/v1.svg?label=Version&message=5.0.0&color=239922">
<a href="https://github.com/FairwindsOps/polaris/releases">
<img src="https://img.shields.io/github/v/release/FairwindsOps/polaris">
</a>
<a href="https://goreportcard.com/report/github.com/FairwindsOps/polaris">
<img src="https://goreportcard.com/badge/github.com/FairwindsOps/polaris">
+36
View File
@@ -0,0 +1,36 @@
successMessage: The ServiceAccount will not be automounted
failureMessage: The ServiceAccount will be automounted
category: Security
target: PodSpec
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
required: ["serviceAccountName"]
properties:
serviceAccountName:
type: string
automountServiceAccountToken:
type: boolean
not:
const: true
additionalSchemaStrings:
ServiceAccount: |
type: object
required:
- metadata
{{ if not (eq .Polaris.PodSpec.automountServiceAccountToken false) }}
- automountServiceAccountToken
{{ end }}
properties:
metadata:
type: object
required: ["name"]
properties:
name:
type: string
const: "{{ .Polaris.PodSpec.serviceAccountName }}"
{{ if not (eq .Polaris.PodSpec.automountServiceAccountToken false) }}
automountServiceAccountToken:
type: boolean
const: false
{{ end }}
+7
View File
@@ -25,3 +25,10 @@ schema:
type: string
not:
const: ''
mutations:
- op: add
path: /resources/limits/cpu
value: 100m
comments:
- find: "cpu: 100m"
comment: "TODO: Set this to the maximum amount of CPU you want your workload to use"
+7
View File
@@ -25,3 +25,10 @@ schema:
type: string
not:
const: ''
mutations:
- op: add
path: /resources/requests/cpu
value: 100m
comments:
- find: "cpu: 100m"
comment: "TODO: Set this to the amount of CPU you want to reserve for your workload"
+5
View File
@@ -24,3 +24,8 @@ schema:
- not:
contains:
pattern: '^(?i)NET_ADMIN$'
mutations:
- op: remove
path: /securityContext/capabilities
+4
View File
@@ -19,3 +19,7 @@ schema:
replicas:
type: integer
minimum: 2
mutations:
- op: add
path: /spec/replicas
value: 3
+4 -1
View File
@@ -1,7 +1,7 @@
successMessage: Host IPC is not configured
failureMessage: Host IPC should not be configured
category: Security
target: Pod
target: PodSpec
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
@@ -9,3 +9,6 @@ schema:
hostIPC:
not:
const: true
mutations:
- op: remove
path: /hostIPC
+4 -1
View File
@@ -1,7 +1,7 @@
successMessage: Host network is not configured
failureMessage: Host network should not be configured
category: Security
target: Pod
target: PodSpec
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
@@ -9,3 +9,6 @@ schema:
hostNetwork:
not:
const: true
mutations:
- op: remove
path: /hostNetwork
+4 -1
View File
@@ -1,7 +1,7 @@
successMessage: Host PID is not configured
failureMessage: Host PID should not be configured
category: Security
target: Pod
target: PodSpec
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
@@ -9,3 +9,6 @@ schema:
hostPID:
not:
const: true
mutations:
- op: remove
path: /hostPID
+1 -1
View File
@@ -12,4 +12,4 @@ schema:
items:
properties:
hostPort:
const: 0
const: 0
+6
View File
@@ -54,3 +54,9 @@ schema:
pattern: '^(?i)KILL$'
- contains:
pattern: '^(?i)AUDIT_WRITE$'
mutations:
- op: remove
path: /securityContext/capabilities
- op: add
path: /securityContext/capabilities
value: {"drop": ["ALL"]}
+89
View File
@@ -0,0 +1,89 @@
successMessage: One of AppArmor, Seccomp, SELinux, or dropping Linux Capabilities are used to restrict containers using unwanted privileges
FailureMessage: Use one of AppArmor, Seccomp, SELinux, or dropping Linux Capabilities to restrict containers using unwanted privileges
category: Security
target: Container
schemaString: |
'$schema': http://json-schema.org/draft-07/schema
definitions:
podOrContainerSeccompProfile:
type: object
{{ $podSeccompProfileType := .Polaris.PodSpec.securityContext.seccompProfile.type }}
required:
{{ if or (not $podSeccompProfileType) (eq $podSeccompProfileType "Unconfined") }}
- securityContext
{{ end }}
properties:
securityContext:
type: object
required:
{{ if or (not $podSeccompProfileType) (eq $podSeccompProfileType "Unconfined") }}
- seccompProfile
{{ end }}
properties:
seccompProfile:
type: object
required:
{{ if or (not $podSeccompProfileType) (eq $podSeccompProfileType "Unconfined") }}
- type
{{ end }}
properties:
type:
type: string
allOf:
- not:
const: "Unconfined"
{{ if or (not $podSeccompProfileType) (eq $podSeccompProfileType "Unconfined") }}
- minLength: 1
{{ end }}
podOrContainerSELinuxOptions:
type: object
{{ $podSELinuxOptions := .Polaris.PodSpec.securityContext.seLinuxOptions }}
{{ if not $podSELinuxOptions }}
required: ["securityContext"]
properties:
securityContext:
type: object
required: ["seLinuxOptions"]
properties:
seLinuxOptions:
type: object
minProperties: 1
{{ end }}
containerDropCapabilities:
type: object
required: ["securityContext"]
properties:
securityContext:
type: object
required: ["capabilities"]
properties:
capabilities:
type: object
required: ["drop"]
properties:
drop:
type: array
minItems: 1
add:
type: array
items:
type: string
not:
pattern: '^(?i)ALL$'
# End of definitions
{{/* Check for AppArmor which uses pod annotations. IF pod fields are missing,
require one of the other hardening measures. */}}
{{ $annotationName := (print "container.apparmor.security.beta.kubernetes.io/" .Polaris.Container.name) }}
{{/* Checking annotations before using index() avoids a nil panic when there are no annotations */}}
{{ $annotationExists := false }}
{{ if .Polaris.PodTemplate.metadata.annotations }}
{{ $annotationExists = index .Polaris "PodTemplate" "metadata" "annotations" $annotationName }}
{{ end }}
{{ if $annotationExists }}
type: object
{{ else }}
anyOf:
- $ref: "#/definitions/podOrContainerSeccompProfile"
- $ref: "#/definitions/podOrContainerSELinuxOptions"
- $ref: "#/definitions/containerDropCapabilities"
{{ end}}
+7
View File
@@ -19,3 +19,10 @@ schema:
type: object
not:
const: null
mutations:
- op: add
path: /livenessProbe
value: {"exec": { "command": [ "cat", "/tmp/healthy" ] }, "initialDelaySeconds": 5, "periodSeconds": 5 }
comments:
- find: "livenessProbe:"
comment: "TODO: Change livenessProbe setting to reflect your health endpoints"
+7
View File
@@ -25,3 +25,10 @@ schema:
type: string
not:
const: ''
mutations:
- op: add
path: /resources/limits/memory
value: "512Mi"
comments:
- find: "memory: 512Mi"
comment: "TODO: Set this to the maximum amount of memory you want your workload to use"
+7
View File
@@ -25,3 +25,10 @@ schema:
type: string
not:
const: ''
mutations:
- op: add
path: /resources/requests/memory
value: "512Mi"
comments:
- find: "memory: 512Mi"
comment: "TODO: Set this to the amount of Memory you want to reserve for your workload"
+49
View File
@@ -0,0 +1,49 @@
successMessage: A NetworkPolicy matches pod labels and contains egress and ingress rules
failureMessage: A NetworkPolicy should match pod labels and contain applied egress and ingress rules
category: Security
target: PodTemplate
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
metadata:
type: object
properties:
labels:
type: object
minProperties: 1
additionalSchemaStrings:
networking.k8s.io/NetworkPolicy: |
type: object
properties:
spec:
type: object
required: ["podSelector", "egress", "ingress"]
properties:
podSelector:
type: object
required: ["matchLabels"]
properties:
matchLabels:
type: object
oneOf:
{{ range $key, $value := .Polaris.PodTemplate.metadata.labels }}
- properties:
"{{ $key }}":
type: string
const: {{ $value }}
required: ["{{ $key }}"]
{{ end }}
egress:
type: array
minItems: 1
ingress:
minItems: 1
type: array
policyTypes:
type: array
allOf:
- contains:
pattern: '^(?i)Egress$'
- contains:
pattern: '^(?i)Ingress$'
+7 -2
View File
@@ -2,7 +2,7 @@ successMessage: Filesystem is read only
failureMessage: Filesystem should be read only
category: Security
target: Container
schemaTarget: Pod
schemaTarget: PodSpec
schema:
'$schema': http://json-schema.org/draft-07/schema
definitions:
@@ -40,4 +40,9 @@ schema:
- securityContext
properties:
securityContext:
$ref: "#/definitions/goodSecurityContext"
$ref: "#/definitions/goodSecurityContext"
mutations:
- op: add
path: /securityContext/readOnlyRootFilesystem
value: true
+5 -1
View File
@@ -1,9 +1,13 @@
successMessage: Priority class has been set
failureMessage: Priority class should be set
category: Security
target: Pod
target: PodSpec
schema:
'$schema': http://json-schema.org/draft-07/schema
type: object
required:
- priorityClassName
mutations:
- op: add
path: /priorityClassName
value: high-priority
+1 -1
View File
@@ -2,7 +2,7 @@ successMessage: Privilege escalation not allowed
failureMessage: Privilege escalation should not be allowed
category: Security
target: Container
schemaTarget: Pod
schemaTarget: PodSpec
schema:
'$schema': http://json-schema.org/draft-07/schema
definitions:
+4
View File
@@ -9,3 +9,7 @@ schema:
properties:
imagePullPolicy:
const: Always
mutations:
- op: add
path: /imagePullPolicy
value: Always
+7
View File
@@ -19,3 +19,10 @@ schema:
type: object
not:
const: null
mutations:
- op: add
path: /readinessProbe
value: {"exec": { "command": [ "cat", "/tmp/healthy" ] }, "initialDelaySeconds": 5, "periodSeconds": 5 }
comments:
- find: "readinessProbe:"
comment: "TODO: Change livenessProbe setting to reflect your health endpoints"
+6 -2
View File
@@ -2,7 +2,7 @@ successMessage: Not running as privileged
failureMessage: Should not be running as privileged
category: Security
target: Container
schemaTarget: Pod
schemaTarget: PodSpec
schema:
'$schema': http://json-schema.org/draft-07/schema
definitions:
@@ -21,4 +21,8 @@ schema:
items:
properties:
securityContext:
$ref: "#/definitions/notBadSecurityContext"
$ref: "#/definitions/notBadSecurityContext"
mutations:
- op: add
path: /securityContext/privileged
value: false
+5 -1
View File
@@ -2,7 +2,7 @@ successMessage: Is not allowed to run as root
failureMessage: Should not be allowed to run as root
category: Security
target: Container
schemaTarget: Pod
schemaTarget: PodSpec
schema:
'$schema': http://json-schema.org/draft-07/schema
definitions:
@@ -50,3 +50,7 @@ schema:
properties:
securityContext:
$ref: "#/definitions/goodSecurityContext"
mutations:
- op: add
path: /securityContext/runAsNonRoot
value: true
+43
View File
@@ -0,0 +1,43 @@
successMessage: The ConfigMap does not contain potentially sensitive content in its keys and values
failureMessage: Potentially sensitive content is detected in the ConfigMap keys or values
category: Security
target: /ConfigMap
schemaString: |
'$schema': http://json-schema.org/draft-07/schema
type: object
required: ["metadata"]
properties:
metadata:
required: ["name"]
properties:
name:
type: string
data:
type: object
propertyNames:
'$comment': These ConfigMap keys will be disallowed.
allOf:
- not:
pattern: '(?i)^AWS_SECRET_ACCESS_KEY$'
- not:
pattern: '(?i)^GOOGLE_APPLICATION_CREDENTIALS$'
- not:
pattern: '(?i)^AZURE_.+KEY$'
- not:
pattern: '(?i)^OCI_CLI_KEY_CONTENT$'
- not:
pattern: '(?i)password'
- not:
pattern: '(?i)token'
- not:
pattern: '(?i)bearer'
- not:
pattern: '(?i)secret'
'$comment': This allows ConfigMap keys not excluded above.
- pattern: '(?i).*'
additionalProperties:
'$comment': These ConfigMap values will be disallowed.
allOf:
- not:
'$comment': THis matches variations like begin private key, begin rsa private key ...
pattern: '(?i)\s*-BEGIN\s+.*PRIVATE KEY-\s*'
+43
View File
@@ -0,0 +1,43 @@
successMessage: The container does not set potentially sensitive environment variables
failureMessage: The container sets potentially sensitive environment variables
category: Security
target: Container
schemaString: |
'$schema': http://json-schema.org/draft-07/schema
type: object
properties:
env:
type: array
items:
type: object
required: ["name"]
properties:
name:
type: string
'$comment': These environment variable names will be disallowed.
allOf:
- not:
pattern: '(?i)^AWS_SECRET_ACCESS_KEY$'
- not:
pattern: '(?i)^GOOGLE_APPLICATION_CREDENTIALS$'
- not:
pattern: '(?i)^AZURE_.+KEY$'
- not:
pattern: '(?i)^OCI_CLI_KEY_CONTENT$'
- not:
pattern: '(?i)password'
- not:
pattern: '(?i)token'
- not:
pattern: '(?i)bearer'
- not:
pattern: '(?i)secret'
'$comment': This allows variable names not excluded above.
- pattern: '(?i).*'
value:
type: string
'$comment': These environment variable values will be disallowed.
allOf:
- not:
'$comment': THis matches variations like begin private key, begin rsa private key ...
pattern: '(?i)\s*-BEGIN\s+.*PRIVATE KEY-\s*'
+37 -10
View File
@@ -24,6 +24,7 @@ import (
"os"
"os/exec"
cfg "github.com/fairwindsops/polaris/pkg/config"
"github.com/fairwindsops/polaris/pkg/kube"
"github.com/fairwindsops/polaris/pkg/validator"
"github.com/sirupsen/logrus"
@@ -31,16 +32,20 @@ import (
"sigs.k8s.io/yaml"
)
var setExitCode bool
var onlyShowFailedTests bool
var minScore int
var auditOutputURL string
var auditOutputFile string
var auditOutputFormat string
var resourceToAudit string
var useColor bool
var helmChart string
var helmValues string
var (
setExitCode bool
onlyShowFailedTests bool
minScore int
auditOutputURL string
auditOutputFile string
auditOutputFormat string
resourceToAudit string
useColor bool
helmChart string
helmValues string
checks []string
auditNamespace string
)
func init() {
rootCmd.AddCommand(auditCmd)
@@ -56,6 +61,8 @@ func init() {
auditCmd.PersistentFlags().StringVar(&resourceToAudit, "resource", "", "Audit a specific resource, in the format namespace/kind/version/name, e.g. nginx-ingress/Deployment.apps/v1/default-backend.")
auditCmd.PersistentFlags().StringVar(&helmChart, "helm-chart", "", "Will fill out Helm template")
auditCmd.PersistentFlags().StringVar(&helmValues, "helm-values", "", "Optional flag to add helm values")
auditCmd.PersistentFlags().StringSliceVar(&checks, "checks", []string{}, "Optional flag to specify specific checks to check")
auditCmd.PersistentFlags().StringVar(&auditNamespace, "namespace", "", "Namespace to audit. Only applies to in-cluster audits")
}
var auditCmd = &cobra.Command{
@@ -66,6 +73,26 @@ var auditCmd = &cobra.Command{
if displayName != "" {
config.DisplayName = displayName
}
if len(checks) > 0 {
targetChecks := make(map[string]bool)
for _, check := range checks {
targetChecks[check] = true
}
for key := range config.Checks {
if isTarget := targetChecks[key]; !isTarget {
config.Checks[key] = cfg.SeverityIgnore
}
}
}
if auditNamespace != "" {
if helmChart != "" {
logrus.Warn("--namespace and --helm-chart are mutually exclusive. --namespace will be ignored.")
}
if auditPath != "" {
logrus.Warn("--namespace and --audit-path are mutually exclusive. --namespace will be ignored.")
}
config.Namespace = auditNamespace
}
if helmChart != "" {
var err error
auditPath, err = ProcessHelmTemplates(helmChart, helmValues)
+179
View File
@@ -0,0 +1,179 @@
// Copyright 2020 FairwindsOps Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package cmd
import (
"bytes"
"errors"
"fmt"
"io"
"io/ioutil"
"os"
"path/filepath"
"strings"
"github.com/fairwindsops/polaris/pkg/kube"
"github.com/fairwindsops/polaris/pkg/mutation"
"github.com/fairwindsops/polaris/pkg/validator"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
yamlV3 "gopkg.in/yaml.v3"
"sigs.k8s.io/yaml"
)
var (
filesPath string
checksToFix []string
fixAll bool
)
func init() {
rootCmd.AddCommand(fixCommand)
fixCommand.PersistentFlags().StringVar(&filesPath, "files-path", "", "mutate and fix one or more YAML files in a specified folder")
fixCommand.PersistentFlags().StringSliceVar(&checksToFix, "checks", []string{}, "Optional flag to specify specific checks to fix eg. checks=hostIPCSet,hostPIDSet and checks=all applies fix to all defined checks mutations")
}
var fixCommand = &cobra.Command{
Use: "fix",
Short: "Fix Infrastructure as code files.",
Long: `Fix Infrastructure as code files.`,
Run: func(cmd *cobra.Command, args []string) {
logrus.Debug("Setting up controller manager")
if filesPath == "" {
logrus.Error("Please specify a file-path flag")
cmd.Help()
os.Exit(1)
}
var yamlFiles []string
fileInfo, err := os.Stat(filesPath)
if err != nil {
logrus.Error(err)
os.Exit(1)
}
if fileInfo.IsDir() {
baseDir := filesPath
if !strings.HasSuffix(filesPath, "/") {
baseDir = baseDir + "/"
}
yamlFiles, err = getYamlFiles(baseDir)
if err != nil {
logrus.Error(err)
os.Exit(1)
}
} else {
yamlFiles = append(yamlFiles, filesPath)
}
var contentStr string
isFirstResource := true
if len(checksToFix) > 0 {
if len(checksToFix) == 1 && checksToFix[0] == "all" {
allchecks := []string{}
for key := range config.Checks {
allchecks = append(allchecks, key)
}
config.Mutations = allchecks
} else {
config.Mutations = checksToFix
}
}
for _, fullFilePath := range yamlFiles {
yamlFile, err := ioutil.ReadFile(fullFilePath)
if err != nil {
logrus.Fatalf("Error reading file with file path %s: %v", fullFilePath, err)
}
dec := yamlV3.NewDecoder(bytes.NewReader(yamlFile))
for {
data := map[string]interface{}{}
err := dec.Decode(&data)
// check it was parsed
if data == nil {
continue
}
// break the loop in case of EOF
if errors.Is(err, io.EOF) {
break
}
if err != nil {
logrus.Fatalf("Error decoding data for file with file path %s: %v", fullFilePath, err)
}
yamlContent, err := yamlV3.Marshal(data)
if err != nil {
logrus.Fatalf("Error marshalling %s: %v", fullFilePath, err)
}
kubeResources := kube.CreateResourceProviderFromYaml(string(yamlContent))
results, err := validator.ApplyAllSchemaChecksToResourceProvider(&config, kubeResources)
if err != nil {
logrus.Fatalf("Error applying schema check to the resources %s: %v", fullFilePath, err)
}
comments, allMutations := mutation.GetMutationsAndCommentsFromResults(results)
updatedYamlContent := string(yamlContent)
if len(allMutations) > 0 {
for _, resources := range kubeResources.Resources {
key := fmt.Sprintf("%s/%s/%s", resources[0].Kind, resources[0].Resource.GetName(), resources[0].Resource.GetNamespace())
mutations := allMutations[key]
mutated, err := mutation.ApplyAllSchemaMutations(&config, kubeResources, resources[0], mutations)
if err != nil {
logrus.Errorf("Error applying schema mutations to the resources: %v", err)
os.Exit(1)
}
mutatedYamlContent, err := yaml.JSONToYAML(mutated.OriginalObjectJSON)
if err != nil {
logrus.Errorf("Error converting JSON to Yaml : %v", err)
os.Exit(1)
}
updatedYamlContent = mutation.UpdateMutatedContentWithComments(string(mutatedYamlContent), comments)
}
}
if isFirstResource {
contentStr = updatedYamlContent
isFirstResource = false
} else {
contentStr += "\n"
contentStr += "---"
contentStr += "\n"
contentStr += updatedYamlContent
}
}
if contentStr != "" {
err = ioutil.WriteFile(fullFilePath, []byte(contentStr), 0644)
if err != nil {
logrus.Fatalf("Error writing output to file: %v", err)
}
}
}
},
}
func getYamlFiles(rootpath string) ([]string, error) {
var list []string
err := filepath.Walk(rootpath, func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}
if filepath.Ext(path) == ".yaml" || filepath.Ext(path) == ".yml" {
list = append(list, path)
}
return nil
})
return list, err
}
+4 -1
View File
@@ -25,10 +25,11 @@ import (
)
var configPath string
var disallowExemptions, disallowConfigExemptions, disallowAnnotationExemptions bool
var disallowExemptions, disallowConfigExemptions, disallowAnnotationExemptions, fixChecks bool
var logLevel string
var auditPath string
var displayName string
var kubeContext string
var (
version string
@@ -37,6 +38,7 @@ var (
func init() {
// Flags
rootCmd.PersistentFlags().StringVarP(&configPath, "config", "c", "", "Location of Polaris configuration file.")
rootCmd.PersistentFlags().StringVarP(&kubeContext, "context", "x", "", "Set the kube context.")
rootCmd.PersistentFlags().BoolVarP(&disallowExemptions, "disallow-exemptions", "", false, "Disallow any configured exemption.")
rootCmd.PersistentFlags().BoolVarP(&disallowConfigExemptions, "disallow-config-exemptions", "", false, "Disallow exemptions set within the configuration file.")
rootCmd.PersistentFlags().BoolVarP(&disallowAnnotationExemptions, "disallow-annotation-exemptions", "", false, "Disallow any exemption defined as a controller annotation.")
@@ -68,6 +70,7 @@ var rootCmd = &cobra.Command{
config.DisallowExemptions = disallowExemptions
config.DisallowConfigExemptions = disallowConfigExemptions
config.DisallowAnnotationExemptions = disallowAnnotationExemptions
config.KubeContext = kubeContext
},
Run: func(cmd *cobra.Command, args []string) {
logrus.Error("You must specify a sub-command.")
+15 -4
View File
@@ -29,11 +29,15 @@ import (
var webhookPort int
var disableWebhookConfigInstaller bool
var enableMutations bool
var enableValidations bool
func init() {
rootCmd.AddCommand(webhookCmd)
webhookCmd.PersistentFlags().IntVarP(&webhookPort, "port", "p", 9876, "Port for the dashboard webserver.")
webhookCmd.PersistentFlags().BoolVar(&disableWebhookConfigInstaller, "disable-webhook-config-installer", false, "disable the installer in the webhook server, so it won't install webhook configuration resources during bootstrapping.")
webhookCmd.PersistentFlags().BoolVar(&disableWebhookConfigInstaller, "disable-webhook-config-installer", false, "Disable the installer in the webhook server, so it won't install webhook configuration resources during bootstrapping.")
webhookCmd.PersistentFlags().BoolVar(&enableValidations, "validate", true, "Enable the validating webhook to reject workloads with issues")
webhookCmd.PersistentFlags().BoolVar(&enableMutations, "mutate", false, "Enable the mutating webhook to modify workloads with issues")
}
var webhookCmd = &cobra.Command{
@@ -61,10 +65,17 @@ var webhookCmd = &cobra.Command{
server.CertName = "tls.crt"
server.KeyName = "tls.key"
// Iterate all the configurations supported controllers to scan and register them for webhooks
// Should only register controllers that are configured to be scanned
fwebhook.NewWebhook(mgr, fwebhook.Validator{Config: config, Client: mgr.GetClient()})
if !enableMutations && !enableValidations {
logrus.Errorf("One of --mutate or --validate must be set to true")
os.Exit(1)
}
if enableValidations {
fwebhook.NewValidateWebhook(mgr, fwebhook.Validator{Config: config, Client: mgr.GetClient()})
}
if enableMutations {
fwebhook.NewMutateWebhook(mgr, fwebhook.Mutator{Config: config, Client: mgr.GetClient()})
}
logrus.Infof("Polaris webhook server listening on port %d", webhookPort)
if err := mgr.Start(signals.SetupSignalHandler()); err != nil {
logrus.Errorf("Error starting manager: %v", err)
-156
View File
@@ -1,156 +0,0 @@
---
# Source: polaris/templates/0-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: polaris
---
# Source: polaris/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: polaris
namespace: polaris
labels:
app: polaris
---
# Source: polaris/templates/rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: polaris
labels:
app: polaris
rules:
# required by controller-runtime code doing a cluster wide lookup
# when it seems namespace would suffice
- apiGroups:
- ''
resources:
- 'nodes'
verbs:
- 'get'
- 'list'
- apiGroups:
- 'monitoring.coreos.com'
resources:
- 'prometheuses'
- 'alertmanagers'
verbs:
- 'get'
- 'list'
---
# Source: polaris/templates/rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: polaris-view
labels:
app: polaris
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: view
subjects:
- kind: ServiceAccount
name: polaris
namespace: polaris
---
# Source: polaris/templates/rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: polaris
labels:
app: polaris
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: polaris
subjects:
- kind: ServiceAccount
name: polaris
namespace: polaris
---
# Source: polaris/templates/dashboard.service.yaml
apiVersion: v1
kind: Service
metadata:
name: polaris-dashboard
namespace: polaris
labels:
app: polaris
annotations:
spec:
ports:
- name: http-dashboard
port: 80
protocol: TCP
targetPort: 8080
selector:
app: polaris
component: dashboard
type: ClusterIP
---
# Source: polaris/templates/dashboard.deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: polaris-dashboard
namespace: polaris
labels:
app: polaris
component: dashboard
spec:
replicas: 2
selector:
matchLabels:
app: polaris
component: dashboard
template:
metadata:
labels:
app: polaris
component: dashboard
spec:
containers:
- command:
- polaris
- dashboard
- --port
- "8080"
image: 'quay.io/fairwinds/polaris:5.0'
imagePullPolicy: 'Always'
name: dashboard
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 20
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 5
periodSeconds: 20
resources:
limits:
cpu: 150m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
securityContext:
allowPrivilegeEscalation: false
privileged: false
readOnlyRootFilesystem: true
runAsNonRoot: true
capabilities:
drop:
- ALL
serviceAccountName: polaris
nodeSelector:
tolerations:
-270
View File
@@ -1,270 +0,0 @@
---
# Source: polaris/templates/0-namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: polaris
---
# Source: polaris/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: polaris
namespace: polaris
labels:
app: polaris
---
# Source: polaris/templates/rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: polaris
labels:
app: polaris
rules:
# required by controller-runtime code doing a cluster wide lookup
# when it seems namespace would suffice
- apiGroups:
- ''
resources:
- 'nodes'
verbs:
- 'get'
- 'list'
- apiGroups:
- 'monitoring.coreos.com'
resources:
- 'prometheuses'
- 'alertmanagers'
verbs:
- 'get'
- 'list'
---
# Source: polaris/templates/rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: polaris-view
labels:
app: polaris
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: view
subjects:
- kind: ServiceAccount
name: polaris
namespace: polaris
---
# Source: polaris/templates/rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: polaris
labels:
app: polaris
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: polaris
subjects:
- kind: ServiceAccount
name: polaris
namespace: polaris
---
# Source: polaris/templates/webhook.service.yaml
apiVersion: v1
kind: Service
metadata:
name: polaris-webhook
namespace: polaris
labels:
app: polaris
spec:
ports:
- name: webhook
port: 443
protocol: TCP
targetPort: 9876
selector:
app: polaris
component: webhook
type: ClusterIP
---
# Source: polaris/templates/webhook.deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: polaris-webhook
namespace: polaris
labels:
app: polaris
component: webhook
spec:
replicas: 2
selector:
matchLabels:
app: polaris
component: webhook
template:
metadata:
labels:
app: polaris
component: webhook
spec:
containers:
- name: webhook
command:
- polaris
- webhook
image: 'quay.io/fairwinds/polaris:5.0'
imagePullPolicy: 'Always'
ports:
- containerPort: 9876
# These are fairly useless readiness/liveness probes for now
# Follow this issue for potential improvements:
# https://github.com/kubernetes-sigs/controller-runtime/issues/356
livenessProbe:
exec:
command:
- sh
- -c
- ps -ef | grep polaris
initialDelaySeconds: 5
periodSeconds: 5
readinessProbe:
exec:
command:
- sh
- -c
- ps -ef | grep polaris
initialDelaySeconds: 5
periodSeconds: 5
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
securityContext:
allowPrivilegeEscalation: false
privileged: false
readOnlyRootFilesystem: true
runAsNonRoot: true
capabilities:
drop:
- ALL
volumeMounts:
- name: secret
mountPath: /opt/cert/
readOnly: true
- name: cr-logs
mountPath: /tmp/
readOnly: false
serviceAccountName: polaris
nodeSelector:
tolerations:
volumes:
- name: secret
secret:
secretName: polaris
- name: cr-logs
emptyDir: {}
---
# Source: polaris/templates/webhook.cert.yaml
apiVersion: cert-manager.io/v1alpha2
kind: Certificate
metadata:
name: polaris-cert
namespace: polaris
labels:
app: polaris
spec:
commonName: polaris-webhook.polaris.svc
dnsNames:
- polaris-webhook.polaris.svc
- polaris-webhook.polaris
- polaris-webhook
- polaris-webhook.polaris.svc.
issuerRef:
kind: Issuer
name: polaris-selfsigned
secretName: polaris
---
# Source: polaris/templates/webhook.cert.yaml
apiVersion: cert-manager.io/v1alpha2
kind: Issuer
metadata:
name: polaris-selfsigned
namespace: polaris
spec:
selfSigned: {}
---
# Source: polaris/templates/webhook.configuration.yaml
apiVersion: admissionregistration.k8s.io/v1beta1
kind: ValidatingWebhookConfiguration
metadata:
name: polaris-webhook
annotations:
cert-manager.io/inject-ca-from: polaris/polaris-cert
webhooks:
- admissionReviewVersions:
- v1beta1
clientConfig:
service:
name: polaris-webhook
namespace: polaris
path: /validate
port: 443
failurePolicy: Fail
matchPolicy: Exact
name: polaris.fairwinds.com
namespaceSelector:
matchExpressions:
- key: control-plane
operator: DoesNotExist
objectSelector:
{}
rules:
- apiGroups:
- apps
apiVersions:
- v1
- v1beta1
- v1beta2
operations:
- CREATE
- UPDATE
resources:
- daemonsets
- deployments
- statefulsets
scope: Namespaced
- apiGroups:
- batch
apiVersions:
- v1
- v1beta1
operations:
- CREATE
- UPDATE
resources:
- jobs
- cronjobs
scope: Namespaced
- apiGroups:
- ""
apiVersions:
- v1
operations:
- CREATE
- UPDATE
resources:
- pods
- replicationcontrollers
scope: Namespaced
sideEffects: None
timeoutSeconds: 10
+14 -5
View File
@@ -25,11 +25,6 @@ If you don't use cert-manager, you'll need to:
* Create a TLS secret in your cluster with a valid certificate that uses that CA
* Pass the name of that secret with the webhook.secretName parameter.
### kubectl
```bash
kubectl apply -f https://github.com/fairwindsops/polaris/releases/latest/download/webhook.yaml
```
### Helm
```bash
helm repo add fairwinds-stable https://charts.fairwinds.com/stable
@@ -50,3 +45,17 @@ output unless we are rejecting a workload altogether.
This means that any checks with a severity of `warning` will still pass webhook validation,
and the only evidence of that warning will either be in the Polaris dashboard or the
Polaris webhook logs. This will change in a future version of Kubernetes.
## Mutating Webhook
By default, the Admission Controller is just pass/fail, but
Polaris can also operate as a mutating webhook for many of the issues it checks for.
This means Polaris will remediate the issue it finds, rather than rejecting
the deployment.
To enable the mutating webhook, add `--set webhook.mutate=true` to your
Helm instlallation command.
By default, the only mutation enabled is `pullPolicyNotAlways`. If you'd like to
enable other mutations, you can set the `webhook.mutations` flag.
+16
View File
@@ -5,6 +5,22 @@ meta:
content: "Fairwinds Polaris | Changelog"
---
## 7.0.1
* Documentation updates
## 7.0.0
* Better support for `polaris fix`
* `target: Pod` is now `target: PodSpec` (to differentiate naked Pods from Controllers)
## 6.0.0
* Preliminary support for `polaris fix` command
* Changes to how Pod owners are determined
* Removed YAML manifests from the `deploy/` directory - Helm is now the default install mechanism
## 5.1.0
* Support `--context` flag for kubecontext
* Treat core Kubernetes controllers (`Deployments`, `StatefulSets`, `DaemonSets`, `CronJobs`) as top-level objects, instead of following owner refs
## 5.0.0
* Renamed `multipleReplicasForDeployment` to `deploymentMissingReplicas`
* Changed `RunAsRootAllowed` and `hostNetworkSet` default severity to `danger`
+3
View File
@@ -20,6 +20,7 @@ webhook
# global flags
-c, --config string Location of Polaris configuration file.
-x, --context string Set the kube context.
--disallow-exemptions Disallow any exemptions from configuration file.
--disallow-config-exemptions Disallow exemptions set within the configuration file.
--disallow-annotation-exemptions Disallow any exemption defined as a controller annotation.
@@ -37,12 +38,14 @@ webhook
# audit flags
--audit-path string If specified, audits one or more YAML files instead of a cluster.
--checks stringArray Optional flag to specify specific checks to check
--color Whether to use color in pretty format. (default true)
--display-name string An optional identifier for the audit.
-f, --format string Output format for results - json, yaml, pretty, or score. (default "json")
--helm-chart string Will fill out Helm template
--helm-values string Optional flag to add helm values
-h, --help help for audit
--namespace string Namespace to audit. Only applies to in-cluster audits
--only-show-failed-tests If specified, audit output will only show failed tests.
--output-file string Destination file for audit results.
--output-url string Destination URL to send audit results.
+3 -46
View File
@@ -73,50 +73,7 @@ Each new pull request should:
- Be up to date and/or rebased on the master branch
## Creating a new release
To create a new release, simply tag this repo with the new version.
### Patch releases
Patch releases only need to change this repo. The Helm chart and deploy scripts
will automatically pull in the latest changes.
If the release involves changes to anything in the `deploy/` folder (e.g. new RBAC permissions),
it needs to be a minor or major release in order to prevent breaking the Helm chart.
1. Create a PR for this repo
1. Bump the version number in:
1. main.go
2. README.md
2. Update CHANGELOG.md
3. Merge your PR
2. Tag the latest branch for this repo
1. Pull the latest commit for the `master` branch (which you just merged in your PR)
2. Run `git tag $VERSION && git push --tags`
3. Make sure CircleCI runs successfully for the new tag - this will push images to quay.io and create a release in GitHub
1. If CircleCI fails, check with Codeowners ASAP
### Minor/Major releases
Minor and major releases need to change both this repository and the
[Helm chart repo](https://github.com/FairwindsOps/charts/).
The steps are:
1. Modify the [Helm chart](https://github.com/FairwindsOps/charts/stable/polaris)
1. Clone the helm charts repo
1. `git clone https://github.com/FairwindsOps/charts`
2. `git checkout -b yourname/update-polaris`
1. Bump the version number in `stable/polaris/Chart.yaml`
2. Make any necessary changes to the chart to support the new version of Polaris (e.g. new RBAC permissions)
3. **Don't merge yet!**
2. Create a PR for this repo
1. Create a new branch named `yourname/update-version`
2. Bump the version number in:
1. main.go
2. README.md
3. Regenerate the deployment files. Assuming you've cloned the charts repo to `~/git/charts`:
1. `CHARTS_DIR=~/git/charts ./scripts/generate-deployment-files.sh`
4. Update CHANGELOG.md
5. Merge your PR
3. Tag the latest branch for this repo
1. Pull the latest for the `master` branch
2. Run `git tag $VERSION && git push --tags`
3. Make sure CircleCI runs successfully for the new tag - this will push images to quay.io and create a release in GitHub
1. If CircleCI fails, check with Codeowners ASAP
4. Create and merge a PR for your changes to the Helm chart
For major and minor releases, don't forget to update the Helm chart at
https://github.com/FairwindsOps/charts
+9 -3
View File
@@ -43,10 +43,11 @@ check ID. Note that you'll also have to set its severity in the `checks` section
* `category` - one of `Security`, `Efficiency`, or `Reliability`
* `target` - specifies the type of resource to check. This can be:
* a group and kind, e.g. `apps/Deployment` or `networking.k8s.io/Ingress`
* `Controller`, to check _any_ resource that contains a pod spec (e.g. Deployments, CronJobs, StatefulSets), as well as naked Pods
* `Pod`, same as `Controller`, but the schema applies to the Pod spec rather than the top-level controller
* `Controller`, to check _any_ resource that creates Pods (e.g. Deployments, CronJobs, StatefulSets), as well as naked Pods
* `PodTemplate`, same as `Controller`, but the schema applies to the Pod template rather than the top-level controller
* `PodSpec`, same as `Controller`, but the schema applies to the Pod spec rather than the top-level controller
* `Container` same as `Controller`, but the schema applies to all Container specs rather than the top-level controller
* `controllers` - if `target` is `Controller`, `Pod` or `Container`, you can use this to change which types of controllers are checked
* `controllers` - if `target` is `Controller`, `PodSpec` or `Container`, you can use this to change which types of controllers are checked
* `controllers.include` - _only_ check these controllers
* `controllers.exclude` - check all controllers except these
* `containers` - if `target` is `Container`, you can use this to decide if `initContainers`, `containers`, or both should be checked
@@ -134,6 +135,11 @@ schema:
const: "{{ .metadata.name }}"
```
* The object available via the go template is the full object, and not limited by `target`.
* A check of `target: PodSpec` can directly access the pod specification via the go template variable `.Polaris.PodSpec`.
* A check of `target: PodTemplate` can directly access the pod template via the go template variable `.Polaris.PodTemplate`.
* A check of `target: Container` can directly access the container being checked via the go template variable `.Polaris.container`. The pod template and pod specification can also be accessed via the respective variables `.Polaris.PodTemplate` and `.Polaris.PodSpec`. Access to pod-level fields allows a container check to consult related fields from the pod, such as `securityContext`.
You can also use the full [Go template syntax](https://golang.org/pkg/text/template/), though
you may need to specify your schema as a string in order to use concepts like `range`. E.g.
this check ensures that at least one of the object's labels is present in `matchLabels`:
-5
View File
@@ -16,11 +16,6 @@ don't conform to best practices.
## Installation
### kubectl
```bash
kubectl apply -f https://github.com/fairwindsops/polaris/releases/latest/download/dashboard.yaml
kubectl port-forward --namespace polaris svc/polaris-dashboard 8080:80
```
### Helm
```bash
helm repo add fairwinds-stable https://charts.fairwinds.com/stable
+26
View File
@@ -25,6 +25,32 @@ brew install FairwindsOps/tap/polaris
polaris version
```
## Checking Infrastructure as Code files
You can audit Kubernetes YAML files by running:
```bash
polaris audit --audit-path ./deploy/ --format=pretty
```
This will print out any issues Polaris finds in your manifests.
Polaris can only check raw YAML manifests. If you'd like to check a Helm template,
you can run `helm template` to generate a manifest that Polaris can check.
## Fixing Issues
Polaris can automatically fix many of the issues it finds. For example, you can run
```bash
polaris fix --files-path ./deploy/ --checks=all
```
to fix any issues inside the `deploy` directory. Polaris may leave
comments next to some changes (e.g. liveness and readiness probes) prompting
the user to set them to something more appropriate given the context of their
application.
Note that not all issues can be automatically fixed.
Currently only raw YAML manifests can be mutated. Helm charts etc.
still need to be changed manually.
## Running in a CI pipeline
### Set minimum score for an exit code
+8 -6
View File
@@ -6141,9 +6141,9 @@
}
},
"node_modules/follow-redirects": {
"version": "1.14.4",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz",
"integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==",
"version": "1.14.8",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
"integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==",
"dev": true,
"funding": [
{
@@ -15341,6 +15341,7 @@
"integrity": "sha512-pM7CR3yXB6L8Gfn6EmX7FLNE3+V/15I3o33GkSNsWvgsMp6HVGXKkXgojrcfUUauyL1LZOdvTmu4enU2RePGHw==",
"dev": true,
"requires": {
"@babel/core": "^7.11.0",
"@babel/helper-compilation-targets": "^7.9.6",
"@babel/helper-module-imports": "^7.8.3",
"@babel/plugin-proposal-class-properties": "^7.8.3",
@@ -15353,6 +15354,7 @@
"@vue/babel-plugin-jsx": "^1.0.3",
"@vue/babel-preset-jsx": "^1.2.4",
"babel-plugin-dynamic-import-node": "^2.3.3",
"core-js": "^3.6.5",
"core-js-compat": "^3.6.5",
"semver": "^6.1.0"
}
@@ -18971,9 +18973,9 @@
}
},
"follow-redirects": {
"version": "1.14.4",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.4.tgz",
"integrity": "sha512-zwGkiSXC1MUJG/qmeIFH2HBJx9u0V46QGUe3YR1fXG8bXQxq7fLj0RjLZQ5nubr9qNJUZrH+xUcwXEoXNpfS+g==",
"version": "1.14.8",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.8.tgz",
"integrity": "sha512-1x0S9UVJHsQprFcEC/qnNzBLcIxsjAV905f/UkQxbclCsoTWlacCNOpQa/anodLl2uaEKFhfWOvM2Qg77+15zA==",
"dev": true
},
"for-in": {
+2 -1
View File
@@ -26,7 +26,8 @@
"scripts": {
"build": "npm run build:readme && npm run build:docs",
"build:docs": "vuepress build -d ../dist/",
"build:readme": "cat ../README.md | grep -v 'ocumentation' | sed \"s/https:\\/\\/\\w\\+.docs.fairwinds.com//g\" > README.md",
"build:metadata": "cat main-metadata.md > README.md || true",
"build:readme": "npm run build:metadata && cat ../README.md | grep -v 'ocumentation' | sed \"s/https:\\/\\/\\w\\+.docs.fairwinds.com//g\" >> README.md",
"check-links": "vuepress check-md",
"serve": "npm run build:readme && vuepress dev --port 3003",
"vuepress": "vuepress"
+6 -1
View File
@@ -12,8 +12,11 @@ checks:
memoryRequestsMissing: warning
memoryLimitsMissing: warning
# security
automountServiceAccountToken: warning
hostIPCSet: danger
hostPIDSet: danger
linuxHardening: danger
missingNetworkPolicy: warning
notReadOnlyRootFilesystem: warning
privilegeEscalationAllowed: danger
runAsRootAllowed: danger
@@ -22,10 +25,13 @@ checks:
insecureCapabilities: warning
hostNetworkSet: danger
hostPortSet: warning
sensitiveContainerEnvVar: danger
sensitiveConfigmapContent: danger
# custom
resourceLimits: warning
imageRegistry: danger
exemptions:
- controllerNames:
- my-network-controller
@@ -86,4 +92,3 @@ customChecks:
type: string
not:
pattern: ^quay.io
+3
View File
@@ -28,6 +28,9 @@ checks:
hostPortSet: warning
tlsSettingsMissing: warning
mutations:
- pullPolicyNotAlways
exemptions:
- namespace: kube-system
controllerNames:
+1 -8
View File
@@ -1,14 +1,7 @@
options:
organization: fairwinds-opensource
organization: fairwinds-production
baseBranch: master
# These images will be scanned for vulnerabilities.
images:
docker:
- quay.io/fairwinds/polaris:$CI_SHA1
# These manifests will be scanned for configuration issues.
manifests:
yaml:
- ./deploy/dashboard.yaml
- ./deploy/webhook.yaml
+82 -14
View File
@@ -1,25 +1,93 @@
module github.com/fairwindsops/polaris
go 1.15
go 1.17
require (
github.com/evanphx/json-patch/v5 v5.6.0
github.com/fatih/color v1.13.0
github.com/gobuffalo/packr/v2 v2.8.1
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.1.3 // indirect
github.com/gobuffalo/packr/v2 v2.8.3
github.com/gorilla/mux v1.8.0
github.com/karrick/godirwalk v1.16.1 // indirect
github.com/qri-io/jsonschema v0.1.1
github.com/rogpeppe/go-internal v1.6.2 // indirect
github.com/sirupsen/logrus v1.8.1
github.com/spf13/cobra v1.2.1
github.com/spf13/cobra v1.5.0
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.7.0
github.com/thoas/go-funk v0.9.1
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
k8s.io/api v0.22.2
k8s.io/apimachinery v0.22.2
k8s.io/client-go v0.22.2
sigs.k8s.io/controller-runtime v0.10.1
github.com/stretchr/testify v1.8.0
github.com/thoas/go-funk v0.9.2
golang.org/x/text v0.3.7 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1
k8s.io/api v0.24.3
k8s.io/apimachinery v0.24.3
k8s.io/client-go v0.24.1
sigs.k8s.io/controller-runtime v0.12.1
sigs.k8s.io/yaml v1.3.0
)
require gomodules.xyz/jsonpatch/v2 v2.2.0
require (
cloud.google.com/go/compute v1.6.1 // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.27 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.20 // 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/beorn7/perks v1.0.1 // indirect
github.com/cespare/xxhash/v2 v2.1.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
github.com/fsnotify/fsnotify v1.5.4 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/swag v0.21.1 // indirect
github.com/gobuffalo/logger v1.0.6 // indirect
github.com/gobuffalo/packd v1.0.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.4.1 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/gnostic v0.6.9 // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/imdario/mergo v0.3.13 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/karrick/godirwalk v1.17.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/markbates/errx v1.1.0 // indirect
github.com/markbates/oncer v1.0.0 // indirect
github.com/markbates/safe v1.0.1 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.12.2 // indirect
github.com/prometheus/client_model v0.2.0 // indirect
github.com/prometheus/common v0.34.0 // indirect
github.com/prometheus/procfs v0.7.3 // indirect
github.com/qri-io/jsonpointer v0.1.1 // indirect
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
golang.org/x/net v0.0.0-20220607020251-c690dde0001d // indirect
golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401 // indirect
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 // indirect
golang.org/x/time v0.0.0-20220411224347-583f2d630306 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
k8s.io/component-base v0.24.1 // indirect
k8s.io/klog/v2 v2.60.1 // indirect
k8s.io/kube-openapi v0.0.0-20220603121420-31174f50af60 // indirect
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect
sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
)
+315 -112
View File
@@ -17,14 +17,29 @@ cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKP
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
cloud.google.com/go v0.100.2 h1:t9Iw5QH5v4XtlEQaCtUY7x6sCABps8sW0acw7e2WQ6Y=
cloud.google.com/go v0.100.2/go.mod h1:4Xra9TjzAeYHrl5+oeLlzbM2k3mjVhZh4UqTZ//w99A=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/compute v0.1.0/go.mod h1:GAesmwr110a34z04OlxYkATPBEfVhkymfTBXtfbBFow=
cloud.google.com/go/compute v1.3.0/go.mod h1:cCZiE1NHEtai4wiufUhW8I8S1JKkAnhnQJWM7YD99wM=
cloud.google.com/go/compute v1.5.0/go.mod h1:9SMHyhJlzhlkJqrPAc839t2BZFTSk6Jdj6mkzQJeu0M=
cloud.google.com/go/compute v1.6.0/go.mod h1:T29tfhtVbq1wvAPo0E3+7vhgmkOYeXjhFvz/FMzPu0s=
cloud.google.com/go/compute v1.6.1 h1:2sMmt8prCn7DPaG4Pmh0N3Inmc8cT8ae5k1M6VJ9Wqc=
cloud.google.com/go/compute v1.6.1/go.mod h1:g85FgpzFvNULZ+S8AYq87axRKuf2Kh7deLqV/jJ3thU=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
@@ -38,18 +53,21 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/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=
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=
github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM=
github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA=
github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q=
github.com/Azure/go-autorest/autorest v0.11.27 h1:F3R3q42aWytozkV8ihzcgMO4OA4cuqr3bNlsEuF6//A=
github.com/Azure/go-autorest/autorest v0.11.27/go.mod h1:7l8ybrIdUmGqZMTD0sRtAr8NvbHjfofbf8RSP2q7w7U=
github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M=
github.com/Azure/go-autorest/autorest/adal v0.9.18/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
github.com/Azure/go-autorest/autorest/adal v0.9.20 h1:gJ3E98kMpFB1MFqQCvA1yFab8vthOeD4VlFRQULxahg=
github.com/Azure/go-autorest/autorest/adal v0.9.20/go.mod h1:XVVeme+LZwABT8K5Lc3hA4nAe8LDBVle26gTrguhhPQ=
github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw=
github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74=
github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk=
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/autorest/mocks v0.4.2 h1:PGN4EDXnuQbojHbU0UWoNvmu9AGVwYHG9/fkDYhtAfw=
github.com/Azure/go-autorest/autorest/mocks v0.4.2/go.mod h1:Vy7OitM9Kei0i1Oj+LvyAWMXJHeKH1MVlzFugfVrmyU=
github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg=
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=
@@ -67,13 +85,13 @@ github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRF
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20210826220005-b48c857c3a0e/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
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=
@@ -82,14 +100,16 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
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/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver/v4 v4.0.0/go.mod h1:IbckMUScFkM3pff0VJDNKRiT6TG/YpiHIM2yvyW5YoQ=
github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0=
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/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 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY=
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/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -97,19 +117,24 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
github.com/cockroachdb/logtags v0.0.0-20190617123548-eb05cc24525f/go.mod h1:i/u985jwjWRlyHXQbwatDASoW0RMlZ/3i9yJHE2xLkI=
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/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-oidc v2.1.0+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/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -121,27 +146,39 @@ github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
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/emicklei/go-restful/v3 v3.7.5-0.20220308211933-7c971ca4d0fd/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw=
github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
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=
github.com/evanphx/json-patch v4.11.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v4.12.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww=
github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
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/flowstack/go-jsonschema v0.1.1/go.mod h1:yL7fNggx1o8rm9RlgXv7hTBWxdBM0rVwpMwimd3F3N0=
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=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
github.com/getkin/kin-openapi v0.76.0/go.mod h1:660oXbgy5JFMKreazJaQTw7o+X00qeSyhcnluiMv+Xg=
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
@@ -150,36 +187,49 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2
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-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
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=
github.com/go-logr/logr v0.4.0 h1:K7/B1jt6fIBQVd4Owv2MqGQClcgf0R266+7C/QjRcLc=
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
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-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/zapr v1.2.0 h1:n4JnPI1T3Qq1SFEi/F8rwLrZERp2bso19PJZDB9dayk=
github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro=
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/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA=
github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU=
github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
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/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/gobuffalo/logger v1.0.3 h1:YaXOTHNPCvkqqA7w05A4v0k2tCdpr+sgFlgINbQ6gqc=
github.com/gobuffalo/logger v1.0.3/go.mod h1:SoeejUwldiS7ZsyCBphOGURmWdwUFXs0J7TCjEhjKxM=
github.com/gobuffalo/packd v1.0.0 h1:6ERZvJHfe24rfFmA9OaoKBdC7+c9sydrytMg8SdFGBM=
github.com/gobuffalo/packd v1.0.0/go.mod h1:6VTc4htmJRFB7u1m/4LeMTWjFoYrUiBkU9Fdec9hrhI=
github.com/gobuffalo/packr/v2 v2.8.1 h1:tkQpju6i3EtMXJ9uoF5GT6kB+LMTimDWD8Xvbz6zDVA=
github.com/gobuffalo/packr/v2 v2.8.1/go.mod h1:c/PLlOuTU+p3SybaJATW3H6lX/iK7xEz5OeMf+NnJpg=
github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU=
github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs=
github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0=
github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY=
github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY=
github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
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=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.2.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang-jwt/jwt/v4 v4.4.1 h1:pC5DB52sCeK48Wlb9oPcdhnjkz1TKt1D/P7WKJ0kUcQ=
github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
@@ -194,6 +244,7 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -212,9 +263,15 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.3/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/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
github.com/google/cel-go v0.10.1/go.mod h1:U7ayypeSkw23szu4GaQTPJGx66c20mx8JklMSxrmI1w=
github.com/google/cel-spec v0.6.0/go.mod h1:Nwjgxy5CbjlPrtCWjeDjUyKMl8w41YBYGjsyDdqk0xA=
github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
github.com/google/gnostic v0.6.9 h1:ZK/5VhkoX835RikCHpSUJV9a+S3e1zLh59YnyWeBW+0=
github.com/google/gnostic v0.6.9/go.mod h1:Nm8234We1lq6iB9OmlgNv3nH91XLLVZHCDayfA3xq+E=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@@ -225,8 +282,11 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE=
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
@@ -234,6 +294,7 @@ github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
@@ -245,20 +306,23 @@ github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
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/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.3 h1:twObb+9XcuH5B9V1TBCvvvZoO6iEdILi2a76PYn5rJI=
github.com/google/uuid v1.1.3/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/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/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
github.com/googleapis/gax-go/v2 v2.2.0/go.mod h1:as02EH8zWkzwUoLbBaFeQ+arQaj/OthfcblKl4IGNaM=
github.com/googleapis/gax-go/v2 v2.3.0/go.mod h1:b8LNqSzNabLiUpXKkY7HAR5jr6bIT99EXz9pXxye9YM=
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.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
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=
@@ -290,33 +354,35 @@ github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpO
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.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/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk=
github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
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/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/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/karrick/godirwalk v1.15.8/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw=
github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
github.com/karrick/godirwalk v1.17.0 h1:b4kY7nqDdioR/6qnbHQyDvmA17u5G1cZ6J+CZXwSWoI=
github.com/karrick/godirwalk v1.17.0/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
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=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
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.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
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/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -326,12 +392,13 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/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/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
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/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI=
github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc=
github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY=
@@ -339,8 +406,9 @@ github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2
github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI=
github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.9 h1:sqDoxXbdeALODt0DAeJCVp38ps9ZogZEAXjus69YV3U=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
@@ -359,14 +427,16 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
github.com/moby/term v0.0.0-20210610120745-9d4ed1856297/go.mod h1:vgPCkQMyxTZ7IDy8SXRufE172gr8+K/JE/7hHFxHW3A=
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/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/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -381,18 +451,22 @@ github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.15.0 h1:WjP/FQ/sk43MRmnEcT+MlDw2TFvkrXlprrPST/IudjU=
github.com/onsi/gomega v1.15.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
@@ -406,8 +480,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_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34=
github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
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=
@@ -417,26 +493,30 @@ github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7q
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/common v0.26.0 h1:iMAkS2TDoNWnKM+Kopnx/8tnEStIfpYA0ur0xQzzhMQ=
github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
github.com/prometheus/common v0.34.0 h1:RBmGO9d/FVjqHT0yUGQwBJhkwKV+wPCn7KGpvfab0uE=
github.com/prometheus/common v0.34.0/go.mod h1:gB3sOl7P0TvJabZpLY5uQMpUqRCPPCyRLCZYc7JZTNE=
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/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
github.com/qri-io/jsonpointer v0.1.0 h1:OcTtTmorodUCRc2CZhj/ZwOET8zVj6uo0ArEmzoThZI=
github.com/qri-io/jsonpointer v0.1.0/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH9v37ZaMV64=
github.com/qri-io/jsonpointer v0.1.1 h1:prVZBZLL6TW5vsSB9fFHFAMBLI4b0ri5vribQlTJiBA=
github.com/qri-io/jsonpointer v0.1.1/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH9v37ZaMV64=
github.com/qri-io/jsonschema v0.1.1 h1:t//Doa/gvMqJ0bDhG7PGIKfaWGGxRVaffp+bcvBGGEk=
github.com/qri-io/jsonschema v0.1.1/go.mod h1:QpzJ6gBQ0GYgGmh7mDQ1YsvvhSgE4rYj0k8t5MBOmUY=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.6.2 h1:aIihoIOHCiLZHxyoNQ+ABL4NKhFTgKLBdMLyEAh98m0=
github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ=
@@ -458,48 +538,56 @@ github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTd
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
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/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g=
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
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/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/thoas/go-funk v0.9.1 h1:O549iLZqPpTUQ10ykd26sZhzD+rmR5pWhuElrhbC20M=
github.com/thoas/go-funk v0.9.1/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q=
github.com/thoas/go-funk v0.9.2 h1:oKlNYv0AY5nyf9g+/GhMgS/UO2ces0QRdPKwkhY3VCk=
github.com/thoas/go-funk v0.9.2/go.mod h1:+IWnUfUmFO1+WVYQWQtIJHeRRdaIyyYglZN7xzUPe4Q=
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/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yuin/goldmark v1.4.1/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/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
go.etcd.io/etcd/client/v3 v3.5.0/go.mod h1:AIKXXVX/DQXtfTEqBryiLTUXwON+GuvO6Z7lLS/oTh0=
go.etcd.io/etcd/client/v3 v3.5.1/go.mod h1:OnjH4M8OnAotwaB2l9bVgZzRFKru7/ZMoS46OtKyd3Q=
go.etcd.io/etcd/pkg/v3 v3.5.0/go.mod h1:UzJGatBQ1lXChBkQF0AuAtkRQMYnHubxAEYIrC3MSsE=
go.etcd.io/etcd/raft/v3 v3.5.0/go.mod h1:UFOHSIvO/nKwd4lhkwabrTD3cqW5yVyYYf/KlD00Szc=
go.etcd.io/etcd/server/v3 v3.5.0/go.mod h1:3Ah5ruV+M+7RZr0+Y/5mNLwC+eQlni+mQmOVdCRJoS4=
@@ -525,15 +613,18 @@ go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqe
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/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
go.uber.org/goleak v1.1.12/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=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE=
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=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
@@ -541,11 +632,13 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191122220453-ac88ee75c92c/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
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/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e h1:T8NU3HyQ8ClP4SEE+KbFlg6n0NhuTsN4MyznaarGsZM=
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -569,7 +662,6 @@ 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/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
@@ -581,8 +673,8 @@ 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/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -596,7 +688,6 @@ golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -628,8 +719,18 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
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-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023 h1:ADo5wSpq2gqaCGQWzk7S5vd//0iyyLeAratkEoG5dLE=
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d h1:4SFsTMi4UahlKoloni7L4eYzhFRifURQLw+yv0QDCx8=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -641,8 +742,17 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 h1:0Ja1LBD+yisY6RWM/BH7TJVXWsSjs2VwBSmvSX4HdBc=
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220309155454-6242fa91716a/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401 h1:zwrSfklXn0gxyLRX/aR+q6cgHbV/ItVyzbPlbA+dkAw=
golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -696,7 +806,6 @@ golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200831180312-196b9ba8737a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -714,15 +823,34 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2 h1:c8PlLMqBbOHoqtjteWm5/kbe6rNY2pbRfbIMVnepueo=
golang.org/x/sys v0.0.0-20210817190340-bfb29a6856f2/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220328115105-d36c6a25d886/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467 h1:CBpWXWQpIRjzmkkA+M7q9Fqnwd2mZr3AFqexg8YTfoM=
golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -730,14 +858,16 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
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/time v0.0.0-20220210224613-90d013bbcef8/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20220411224347-583f2d630306 h1:+gHMid33q6pen7kv9xvT+JRinntgeXO2AeZVd0AWD3w=
golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -775,7 +905,6 @@ golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200308013534-11ec41452d41/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
@@ -795,13 +924,18 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
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=
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/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=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
@@ -826,6 +960,21 @@ google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjR
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
google.golang.org/api v0.67.0/go.mod h1:ShHKP8E60yPsKNw/w8w+VYaj9H6buA5UqDp8dhbQZ6g=
google.golang.org/api v0.70.0/go.mod h1:Bs4ZM2HGifEvXwd50TtW70ovgJffJYw2oRCOFU/SkfA=
google.golang.org/api v0.71.0/go.mod h1:4PyU6e6JogV1f9eA4voyrTY2batOLdgZ5qZ5HOCc4j8=
google.golang.org/api v0.74.0/go.mod h1:ZpfMZOVRMywNyvJFeqL9HRWBgAuRfSjJFpe9QtRRyDs=
google.golang.org/api v0.75.0/go.mod h1:pU9QmyHLnzlpar1Mjt4IbapUCy8J+6HD6GeELN69ljA=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -867,6 +1016,7 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201102152239-715cce707fb0/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
@@ -876,10 +1026,40 @@ 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-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211221195035-429b39de9b1c/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220107163113-42d7afdf6368/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220126215142-9970aeb2e350/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220207164111-0872dc986b00/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20220218161850-94dd64e39d7c/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220222213610-43724f9ea8cf/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220304144024-325a89244dc8/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220310185008-1973136f34c6/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI=
google.golang.org/genproto v0.0.0-20220324131243-acbaeb5b85eb/go.mod h1:hAL49I2IFola2sVEjAn7MEwsja0xp51I0tlGAf9hz4E=
google.golang.org/genproto v0.0.0-20220407144326-9054f6ed7bac/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220413183235-5e96e2839df9/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220414192740-2d67ff6cf2b4/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/genproto v0.0.0-20220421151946-72621c1f0bd3/go.mod h1:8w6bsBMX6yCPbAVTeqQHvzxW0EIFigd5lZyahWgyfDo=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
@@ -898,7 +1078,15 @@ 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.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -910,8 +1098,10 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
@@ -941,8 +1131,10 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -952,37 +1144,48 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.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/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/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/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/api v0.24.0/go.mod h1:5Jl90IUrJHUJYEMANRURMiVvJ0g7Ax7r3R1bqO8zx8I=
k8s.io/api v0.24.1/go.mod h1:JhoOvNiLXKTPQ60zh2g0ewpA+bnEYf5q44Flhquh4vQ=
k8s.io/api v0.24.3 h1:tt55QEmKd6L2k5DP6G/ZzdMQKvG5ro4H4teClqm0sTY=
k8s.io/api v0.24.3/go.mod h1:elGR/XSZrS7z7cSZPzVWaycpJuGIw57j9b95/1PdJNI=
k8s.io/apiextensions-apiserver v0.24.0 h1:JfgFqbA8gKJ/uDT++feAqk9jBIwNnL9YGdQvaI9DLtY=
k8s.io/apiextensions-apiserver v0.24.0/go.mod h1:iuVe4aEpe6827lvO6yWQVxiPSpPoSKVjkq+MIdg84cM=
k8s.io/apimachinery v0.24.0/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
k8s.io/apimachinery v0.24.1/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
k8s.io/apimachinery v0.24.3 h1:hrFiNSA2cBZqllakVYyH/VyEh4B581bQRmqATJSeQTg=
k8s.io/apimachinery v0.24.3/go.mod h1:82Bi4sCzVBdpYjyI4jY6aHX+YCUchUIrZrXKedjd2UM=
k8s.io/apiserver v0.24.0/go.mod h1:WFx2yiOMawnogNToVvUYT9nn1jaIkMKj41ZYCVycsBA=
k8s.io/client-go v0.24.0/go.mod h1:VFPQET+cAFpYxh6Bq6f4xyMY80G6jKKktU6G0m00VDw=
k8s.io/client-go v0.24.1 h1:w1hNdI9PFrzu3OlovVeTnf4oHDt+FJLd9Ndluvnb42E=
k8s.io/client-go v0.24.1/go.mod h1:f1kIDqcEYmwXS/vTbbhopMUbhKp2JhOeVTfxgaCIlF8=
k8s.io/code-generator v0.24.0/go.mod h1:dpVhs00hTuTdTY6jvVxvTFCk6gSMrtfRydbhZwHI15w=
k8s.io/component-base v0.24.0/go.mod h1:Dgazgon0i7KYUsS8krG8muGiMVtUZxG037l1MKyXgrA=
k8s.io/component-base v0.24.1 h1:APv6W/YmfOWZfo+XJ1mZwep/f7g7Tpwvdbo9CQLDuts=
k8s.io/component-base v0.24.1/go.mod h1:DW5vQGYVCog8WYpNob3PMmmsY8A3L9QZNg4j/dV3s38=
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/gengo v0.0.0-20211129171323-c02415ce4185/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=
k8s.io/klog/v2 v2.9.0 h1:D7HV+n1V57XeZ0m6tdRkfknthUaM06VFbWldOFh8kzM=
k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e h1:KLHHjkdQFomZy8+06csTWZ0m1343QqxZhR2LJ1OxCYM=
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=
k8s.io/klog/v2 v2.60.1 h1:VW25q3bZx9uE3vvdL6M8ezOX79vA2Aq1nEWLqNQclHc=
k8s.io/klog/v2 v2.60.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42/go.mod h1:Z/45zLw8lUo4wdiUkI+v/ImEGAvu3WatcZl3lPMR4Rk=
k8s.io/kube-openapi v0.0.0-20220603121420-31174f50af60 h1:cE/M8rmDQgibspuSm+X1iW16ByTImtEaapgaHoVSLX4=
k8s.io/kube-openapi v0.0.0-20220603121420-31174f50af60/go.mod h1:ouUzE1U2mEv//HRoBwYLFE5pdqjIebvtX361vtEIlBI=
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 h1:HNSDgDCrr/6Ly3WEGKZftiE7IY19Vz2GdbOCyI4qqhc=
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.22/go.mod h1:LEScyzhFmoF5pso/YSeBstl57mOzx9xlU9n85RGrDQg=
sigs.k8s.io/controller-runtime v0.10.1 h1:+eLHgY/VrJWnfg6iXUqhCUqNXgPH1NZeP9drNAAgWlg=
sigs.k8s.io/controller-runtime v0.10.1/go.mod h1:CQp8eyUQZ/Q7PJvnIrB6/hgfTC1kBkGylwsLgOQi1WY=
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.0.30/go.mod h1:fEO7lRTdivWO2qYVCVG7dEADOMo/MLDCVr8So2g88Uw=
sigs.k8s.io/controller-runtime v0.12.1 h1:4BJY01xe9zKQti8oRjj/NeHKRXthf1YkYJAgLONFFoI=
sigs.k8s.io/controller-runtime v0.12.1/go.mod h1:BKhxlA4l7FPK4AQcsuL4X6vZeWnKDXez/vp1Y8dxTU0=
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY=
sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124 h1:2sgAQQcY0dEW2SsQwTXhQV4vO6+rSslYx8K3XmM5hqQ=
sigs.k8s.io/json v0.0.0-20220525155127-227cbc7cc124/go.mod h1:B+TnT182UBxE84DiCz4CVE26eOSDAeYCpfDnC2kdKMY=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/structured-merge-diff/v4 v4.1.2 h1:Hr/htKFmJEbtMgS/UD0N+gtgctAqz81t3nu+sPzynno=
sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 h1:bKCqE9GvQ5tiVHn5rfn1r+yao3aLQEaLzkkmAkf+A6Y=
sigs.k8s.io/structured-merge-diff/v4 v4.2.1/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
+5 -3
View File
@@ -18,9 +18,11 @@ import (
cmd "github.com/fairwindsops/polaris/cmd/polaris"
)
const (
// Version represents the current release version of Polaris
Version = "5.0.0"
var (
// Version is set during build
Version = "development"
// Commit is set during build
Commit = ""
)
func main() {
+19
View File
@@ -1,3 +1,17 @@
// Copyright 2022 FairwindsOps, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
@@ -18,6 +32,7 @@ var (
"hostIPCSet",
"hostPIDSet",
"hostNetworkSet",
"automountServiceAccountToken",
// Container checks
"memoryLimitsMissing",
"memoryRequestsMissing",
@@ -35,11 +50,15 @@ var (
"dangerousCapabilities",
"insecureCapabilities",
"priorityClassNotSet",
"linuxHardening",
"sensitiveContainerEnvVar",
// Other checks
"tlsSettingsMissing",
"pdbDisruptionsIsZero",
"metadataAndNameMismatched",
"missingPodDisruptionBudget",
"missingNetworkPolicy",
"sensitiveConfigmapContent",
}
)
+3
View File
@@ -36,6 +36,9 @@ type Configuration struct {
DisallowExemptions bool `json:"disallowExemptions"`
DisallowConfigExemptions bool `json:"disallowConfigExemptions"`
DisallowAnnotationExemptions bool `json:"disallowAnnotationExemptions"`
Mutations []string `json:"mutations"`
KubeContext string `json:"kubeContext"`
Namespace string `json:"namespace"`
}
// Exemption represents an exemption to normal rules
+14
View File
@@ -1,3 +1,17 @@
// Copyright 2022 FairwindsOps, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
+41 -5
View File
@@ -1,3 +1,17 @@
// Copyright 2022 FairwindsOps, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package config
import (
@@ -11,6 +25,7 @@ import (
"github.com/qri-io/jsonschema"
"github.com/thoas/go-funk"
"gomodules.xyz/jsonpatch/v2"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
k8sYaml "k8s.io/apimachinery/pkg/util/yaml"
@@ -24,15 +39,24 @@ const (
TargetController TargetKind = "Controller"
// TargetContainer points to the container spec
TargetContainer TargetKind = "Container"
// TargetPod points to the pod spec
TargetPod TargetKind = "Pod"
// TargetPodSpec points to the pod spec
TargetPodSpec TargetKind = "PodSpec"
// TargetPodTemplate points to the pod template
TargetPodTemplate TargetKind = "PodTemplate"
)
// HandledTargets is a list of target names that are explicitly handled
var HandledTargets = []TargetKind{
TargetController,
TargetContainer,
TargetPod,
TargetPodSpec,
TargetPodTemplate,
}
// MutationComment is the comments added to a mutated file
type MutationComment struct {
Find string `yaml:"find" json:"find"`
Comment string `yaml:"comment" json:"comment"`
}
// SchemaCheck is a Polaris check that runs using JSON Schema
@@ -51,6 +75,8 @@ type SchemaCheck struct {
AdditionalSchemas map[string]map[string]interface{} `yaml:"additionalSchemas" json:"additionalSchemas"`
AdditionalSchemaStrings map[string]string `yaml:"additionalSchemaStrings" json:"additionalSchemaStrings"`
AdditionalValidators map[string]jsonschema.RootSchema `yaml:"-" json:"-"`
Mutations []jsonpatch.Operation `yaml:"mutations" json:"mutations"`
Comments []MutationComment `yaml:"comments" json:"comments"`
}
type resourceMinimum string
@@ -230,11 +256,16 @@ func (check SchemaCheck) TemplateForResource(res interface{}) (*SchemaCheck, err
return &newCheck, err
}
// CheckPod checks a pod spec against the schema
func (check SchemaCheck) CheckPod(pod *corev1.PodSpec) (bool, []jsonschema.ValError, error) {
// CheckPodSpec checks a pod spec against the schema
func (check SchemaCheck) CheckPodSpec(pod *corev1.PodSpec) (bool, []jsonschema.ValError, error) {
return check.CheckObject(pod)
}
// CheckPodTemplate checks a pod template against the schema
func (check SchemaCheck) CheckPodTemplate(podTemplate interface{}) (bool, []jsonschema.ValError, error) {
return check.CheckObject(podTemplate)
}
// CheckController checks a controler's spec against the schema
func (check SchemaCheck) CheckController(bytes []byte) (bool, []jsonschema.ValError, error) {
errs, err := check.Validator.ValidateBytes(bytes)
@@ -281,6 +312,11 @@ func (check SchemaCheck) CheckAdditionalObjects(groupkind string, objects []inte
// IsActionable decides if this check applies to a particular target
func (check SchemaCheck) IsActionable(target TargetKind, kind string, isInit bool) bool {
if funk.Contains(HandledTargets, target) {
if check.Target == TargetPodTemplate && target == TargetPodSpec {
// A target=PodSpec and check.Target=PodTemplate is expected
// because applyPodSchemaChecks() explicitly sets check.Target
return true
}
if check.Target != target {
return false
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

+14 -1
View File
@@ -1,3 +1,17 @@
// Copyright 2022 FairwindsOps, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package dashboard
import (
@@ -238,4 +252,3 @@ func TestStringInSlice(t *testing.T) {
assert.Equal(t, expectedOutput, actual)
assert.NotEqual(t, true, actual)
}
+1 -1
View File
@@ -87,7 +87,7 @@
<a class="align-self-center"
target="_blank"
href="https://www.fairwinds.com/polaris-user-insights-demo?utm_source=polaris&utm_medium=ad&utm_campaign=polarisad">
<img src="static/images/FW_Insights_Polaris.svg" />
<img src="static/images/benchmark.png" />
</a>
</div>
+74 -8
View File
@@ -1,3 +1,17 @@
// Copyright 2022 FairwindsOps, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package kube
import (
@@ -21,21 +35,29 @@ type GenericResource struct {
ObjectMeta kubeAPIMetaV1.Object
Resource unstructured.Unstructured
PodSpec *kubeAPICoreV1.PodSpec
PodTemplate interface{}
OriginalObjectJSON []byte
}
// NewGenericResourceFromUnstructured creates a workload from an unstructured.Unstructured
func NewGenericResourceFromUnstructured(unst unstructured.Unstructured) (GenericResource, error) {
func NewGenericResourceFromUnstructured(unst unstructured.Unstructured, podSpecMap interface{}) (GenericResource, error) {
if unst.GetCreationTimestamp().Time.IsZero() {
unstructured.RemoveNestedField(unst.Object, "metadata", "creationTimestamp")
unstructured.RemoveNestedField(unst.Object, "status")
}
workload := GenericResource{
Kind: unst.GetKind(),
Resource: unst,
}
objMeta, err := meta.Accessor(&unst)
if err != nil {
return workload, err
}
workload.ObjectMeta = objMeta
workload.PodTemplate, err = GetPodTemplate(unst.UnstructuredContent())
if err != nil {
return workload, err
}
b, err := json.Marshal(&unst)
if err != nil {
@@ -47,7 +69,9 @@ func NewGenericResourceFromUnstructured(unst unstructured.Unstructured) (Generic
if err != nil {
return workload, err
}
podSpecMap := GetPodSpec(m)
if podSpecMap == nil {
podSpecMap = GetPodSpec(m)
}
if podSpecMap != nil {
b, err = json.Marshal(podSpecMap)
if err != nil {
@@ -65,10 +89,15 @@ func NewGenericResourceFromUnstructured(unst unstructured.Unstructured) (Generic
// NewGenericResourceFromPod builds a new workload for a given Pod without looking at parents
func NewGenericResourceFromPod(podResource kubeAPICoreV1.Pod, originalObject interface{}) (GenericResource, error) {
podMap, err := SerializePod(&podResource)
if err != nil {
return GenericResource{}, err
}
workload := GenericResource{
Kind: "Pod",
PodSpec: &podResource.Spec,
ObjectMeta: podResource.ObjectMeta.GetObjectMeta(),
Kind: "Pod",
PodSpec: &podResource.Spec,
PodTemplate: podMap,
ObjectMeta: podResource.ObjectMeta.GetObjectMeta(),
}
if originalObject != nil {
bytes, err := json.Marshal(originalObject)
@@ -99,7 +128,7 @@ func NewGenericResourceFromBytes(contentBytes []byte) (GenericResource, error) {
if err != nil {
return GenericResource{}, err
}
return NewGenericResourceFromUnstructured(unst)
return NewGenericResourceFromUnstructured(unst, nil)
}
// ResolveControllerFromPod builds a new workload for a given Pod
@@ -121,6 +150,8 @@ func resolveControllerFromPod(ctx context.Context, podResource kubeAPICoreV1.Pod
}
topKind := "Pod"
topMeta := podWorkload.ObjectMeta
var topPodSpec interface{}
topPodSpec = podWorkload.Resource.Object
owners := podResource.ObjectMeta.GetOwnerReferences()
lastKey := ""
for len(owners) > 0 {
@@ -153,13 +184,17 @@ func resolveControllerFromPod(ctx context.Context, podResource kubeAPICoreV1.Pod
logrus.Warnf("Error retrieving parent metadata %s of API %s and Kind %s because of error: %v ", firstOwner.Name, firstOwner.APIVersion, firstOwner.Kind, err)
return GenericResource{}, err
}
podSpec := GetPodSpec(abstractObject.Object)
if podSpec != nil {
topPodSpec = podSpec
}
topMeta = objMeta
owners = abstractObject.GetOwnerReferences()
}
if lastKey != "" {
unst := objectCache[lastKey]
return NewGenericResourceFromUnstructured(unst)
return NewGenericResourceFromUnstructured(unst, topPodSpec)
}
workload, err := NewGenericResourceFromPod(podResource, podResource)
if err != nil {
@@ -212,3 +247,34 @@ func GetPodSpec(yaml map[string]interface{}) interface{} {
}
return nil
}
// GetPodTemplate looks inside arbitrary YAML for a Pod template, containing
// fields `spec.containers`.
// For example, it returns the `spec.template` level of a Kubernetes Deployment yaml.
func GetPodTemplate(yaml map[string]interface{}) (podTemplate interface{}, err error) {
if yamlSpec, ok := yaml["spec"]; ok {
if yamlSpecMap, ok := yamlSpec.(map[string]interface{}); ok {
if _, ok := yamlSpecMap["containers"]; ok {
// This is a hack around unstructured.SetNestedField using DeepCopy which does
// not support the type int, and panics.
// Related: https://github.com/kubernetes/kubernetes/issues/62769
podTemplateJSON, err := json.Marshal(yaml)
if err != nil {
return nil, err
}
podTemplateMap := make(map[string]interface{})
err = json.Unmarshal(podTemplateJSON, &podTemplateMap)
if err != nil {
return nil, err
}
return podTemplateMap, nil
}
}
}
for _, podSpecField := range podSpecFields {
if childYaml, ok := yaml[podSpecField]; ok {
return GetPodTemplate(childYaml.(map[string]interface{}))
}
}
return nil, nil
}
+113 -18
View File
@@ -1,8 +1,23 @@
// Copyright 2022 FairwindsOps, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package kube
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"io/ioutil"
@@ -44,7 +59,12 @@ type resourceKindMap map[string][]GenericResource
func (rkm resourceKindMap) addResource(r GenericResource) {
gvk := r.Resource.GroupVersionKind()
key := gvk.Group + "/" + gvk.Kind
var key string
if gvk.Group != "" {
key = gvk.Group + "/" + gvk.Kind
} else {
key = gvk.Kind
}
rkm[key] = append(rkm[key], r)
}
@@ -168,7 +188,7 @@ func CreateResourceProviderFromResource(ctx context.Context, workload string) (*
logrus.Errorf("Could not find workload %s: %v", workload, err)
return nil, err
}
workloadObj, err := NewGenericResourceFromUnstructured(*obj)
workloadObj, err := NewGenericResourceFromUnstructured(*obj, nil)
if err != nil {
logrus.Errorf("Could not parse workload %s: %v", workload, err)
return nil, err
@@ -201,7 +221,11 @@ func CreateResourceProviderFromPath(directory string) (*ResourceProvider, error)
logrus.Errorf("Error reading file: %v", path)
return err
}
return resources.addResourcesFromYaml(string(contents))
err = resources.addResourcesFromYaml(string(contents))
if err != nil {
logrus.Warnf("Skipping %s: cannot add resource from YAML: %v", path, err)
}
return nil
}
err := filepath.Walk(directory, visitFile)
@@ -211,9 +235,16 @@ func CreateResourceProviderFromPath(directory string) (*ResourceProvider, error)
return &resources, nil
}
// CreateResourceProviderFromYaml returns a new ResourceProvider using the yaml
func CreateResourceProviderFromYaml(yamlContent string) *ResourceProvider {
resources := newResourceProvider("unknown", "Content", "unknown")
resources.addResourcesFromYaml(string(yamlContent))
return &resources
}
// CreateResourceProviderFromCluster creates a new ResourceProvider using live data from a cluster
func CreateResourceProviderFromCluster(ctx context.Context, c conf.Configuration) (*ResourceProvider, error) {
kubeConf, configError := config.GetConfig()
kubeConf, configError := config.GetConfigWithContext(c.KubeContext)
if configError != nil {
logrus.Errorf("Error fetching KubeConfig: %v", configError)
return nil, configError
@@ -239,19 +270,38 @@ func CreateResourceProviderFromAPI(ctx context.Context, kube kubernetes.Interfac
logrus.Errorf("Error fetching Cluster API version: %v", err)
return nil, err
}
provider := newResourceProvider(serverVersion.Major+"."+serverVersion.Minor, "Cluster", clusterName)
sourceType := "Cluster"
if c.Namespace != "" {
logrus.Debug("namespace is specififed in config, setting source type to ClusterNamespace")
sourceType = "ClusterNamespace"
}
provider := newResourceProvider(serverVersion.Major+"."+serverVersion.Minor, sourceType, clusterName)
nodes, err := kube.CoreV1().Nodes().List(ctx, listOpts)
if err != nil {
logrus.Errorf("Error fetching Nodes: %v", err)
return nil, err
}
namespaces, err := kube.CoreV1().Namespaces().List(ctx, listOpts)
if err != nil {
logrus.Errorf("Error fetching Namespaces: %v", err)
return nil, err
var namespaces *corev1.NamespaceList
if c.Namespace != "" {
ns, err := kube.CoreV1().Namespaces().Get(ctx, c.Namespace, metav1.GetOptions{})
if err != nil {
return nil, err
}
namespaces = &corev1.NamespaceList{
Items: []corev1.Namespace{*ns},
}
} else {
nsList, err := kube.CoreV1().Namespaces().List(ctx, listOpts)
if err != nil {
logrus.Errorf("Error fetching Namespaces: %v", err)
return nil, err
}
namespaces = nsList
}
pods, err := kube.CoreV1().Pods("").List(ctx, listOpts)
pods, err := kube.CoreV1().Pods(c.Namespace).List(ctx, listOpts)
if err != nil {
logrus.Errorf("Error fetching Pods: %v", err)
return nil, err
@@ -287,6 +337,7 @@ func CreateResourceProviderFromAPI(ctx context.Context, kube kubernetes.Interfac
}
}
var kubernetesResources []GenericResource
for _, kind := range additionalKinds {
groupKind := parseGroupKind(maybeTransformKindIntoGroupKind(string(kind)))
mapping, err := (restMapper).RESTMapping(groupKind)
@@ -295,17 +346,17 @@ func CreateResourceProviderFromAPI(ctx context.Context, kube kubernetes.Interfac
return nil, err
}
objects, err := (*dynamic).Resource(mapping.Resource).Namespace("").List(ctx, metav1.ListOptions{})
objects, err := (*dynamic).Resource(mapping.Resource).Namespace(c.Namespace).List(ctx, metav1.ListOptions{})
if err != nil {
logrus.Warnf("Error retrieving parent object API %s and Kind %s because of error: %v", mapping.Resource.Version, mapping.Resource.Resource, err)
return nil, err
}
for _, obj := range objects.Items {
res, err := NewGenericResourceFromUnstructured(obj)
res, err := NewGenericResourceFromUnstructured(obj, nil)
if err != nil {
return nil, err
}
provider.Resources.addResource(res)
kubernetesResources = append(kubernetesResources, res)
}
}
@@ -316,9 +367,12 @@ func CreateResourceProviderFromAPI(ctx context.Context, kube kubernetes.Interfac
logrus.Errorf("Error loading controllers from pods: %v", err)
return nil, err
}
// resources loaded from custom checks can also contain controllers and thus would be added twice to the provider
kubernetesResources = deduplicateControllers(append(kubernetesResources, controllers...))
provider.Nodes = nodes.Items
provider.Namespaces = namespaces.Items
provider.Resources.addResources(controllers)
provider.Resources.addResources(kubernetesResources)
return &provider, nil
}
@@ -341,14 +395,14 @@ func LoadControllers(ctx context.Context, pods []corev1.Pod, dynamicClientPointe
}
interfaces = append(interfaces, workload)
}
return deduplicateControllers(interfaces), nil
return interfaces, nil
}
// Because the controllers with an Owner take on the name of the Owner, this eliminates any duplicates.
// In cases like CronJobs older children can hang around, so this takes the most recent.
func deduplicateControllers(inputControllers []GenericResource) []GenericResource {
func deduplicateControllers(inputResources []GenericResource) []GenericResource {
controllerMap := make(map[string]GenericResource)
for _, controller := range inputControllers {
for _, controller := range inputResources {
key := controller.ObjectMeta.GetNamespace() + "/" + controller.Kind + "/" + controller.ObjectMeta.GetName()
oldController, ok := controllerMap[key]
if !ok || controller.ObjectMeta.GetCreationTimestamp().Time.After(oldController.ObjectMeta.GetCreationTimestamp().Time) {
@@ -399,7 +453,6 @@ func (resources *ResourceProvider) addResourceFromString(contents string) error
decoder = k8sYaml.NewYAMLOrJSONDecoder(bytes.NewReader(contentBytes), 1000)
if err != nil {
logrus.Errorf("Invalid YAML: %s", string(contents))
return err
}
if resource.Kind == "Namespace" {
@@ -428,3 +481,45 @@ func (resources *ResourceProvider) addResourceFromString(contents string) error
}
return err
}
// SerializePodSpec converts a typed PodSpec into a map[string]interface{}
func SerializePodSpec(pod *corev1.PodSpec) (map[string]interface{}, error) {
podJSON, err := json.Marshal(pod)
if err != nil {
return nil, err
}
podMap := make(map[string]interface{})
err = json.Unmarshal(podJSON, &podMap)
if err != nil {
return nil, err
}
return podMap, nil
}
// SerializePod converts a typed Pod into a map[string]interface{}
func SerializePod(pod *corev1.Pod) (map[string]interface{}, error) {
podJSON, err := json.Marshal(pod)
if err != nil {
return nil, err
}
podMap := make(map[string]interface{})
err = json.Unmarshal(podJSON, &podMap)
if err != nil {
return nil, err
}
return podMap, nil
}
// SerializeContainer converts a typed Container into a map[string]interface{}
func SerializeContainer(container *corev1.Container) (map[string]interface{}, error) {
containerJSON, err := json.Marshal(container)
if err != nil {
return nil, err
}
containerMap := make(map[string]interface{})
err = json.Unmarshal(containerJSON, &containerMap)
if err != nil {
return nil, err
}
return containerMap, nil
}
+77 -16
View File
@@ -1,3 +1,17 @@
// Copyright 2022 FairwindsOps, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package kube
import (
@@ -60,7 +74,7 @@ func TestGetMultipleResourceFromSingleFile(t *testing.T) {
func TestGetMultipleResourceFromBadFile(t *testing.T) {
_, err := CreateResourceProviderFromPath("./test_files/test_3")
assert.NotEqual(t, nil, err, "CreateResource From Path should fail with bad yaml")
assert.Equal(t, nil, err, "CreateResource From Path should not fail with bad yaml")
}
func TestAddResourcesFromReader(t *testing.T) {
@@ -83,15 +97,6 @@ func TestAddResourcesFromReader(t *testing.T) {
func TestGetResourceFromAPI(t *testing.T) {
k8s, dynamicInterface := test.SetupTestAPI(test.GetMockControllers("test")...)
resources, err := CreateResourceProviderFromAPI(context.Background(), k8s, "test", &dynamicInterface, conf.Configuration{})
assert.Equal(t, nil, err, "Error should be nil")
assert.Equal(t, "Cluster", resources.SourceType, "Should have type Path")
assert.Equal(t, "test", resources.SourceName, "Should have source name")
assert.IsType(t, time.Now(), resources.CreationTime, "Creation time should be set")
assert.Equal(t, 0, len(resources.Nodes), "Should not have any nodes")
assert.Equal(t, 5, len(resources.Resources), "Should have 5 controllers")
expectedNames := map[string]bool{
"deploy": false,
@@ -100,12 +105,68 @@ func TestGetResourceFromAPI(t *testing.T) {
"statefulset": false,
"daemonset": false,
}
for _, controllers := range resources.Resources {
for _, ctrl := range controllers {
expectedNames[ctrl.ObjectMeta.GetName()] = true
}
tests := []struct {
name string
config conf.Configuration
want *ResourceProvider
wantErr bool
clusterName string
}{
{
name: "standard",
config: conf.Configuration{},
clusterName: "test1",
want: &ResourceProvider{
SourceType: "Cluster",
SourceName: "test1",
CreationTime: time.Now(),
},
},
{
name: "namespaced",
config: conf.Configuration{
Namespace: "test",
},
clusterName: "test2",
want: &ResourceProvider{
SourceType: "ClusterNamespace",
SourceName: "test2",
CreationTime: time.Now(),
},
},
{
name: "namespace does not exist",
config: conf.Configuration{
Namespace: "test3",
},
clusterName: "test3",
wantErr: true,
},
}
for name, val := range expectedNames {
assert.Equal(t, true, val, name)
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
resources, err := CreateResourceProviderFromAPI(context.Background(), k8s, tt.clusterName, &dynamicInterface, tt.config)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.want.SourceType, resources.SourceType)
assert.Equal(t, tt.want.SourceName, resources.SourceName)
assert.IsType(t, tt.want.CreationTime, resources.CreationTime)
assert.Equal(t, 0, len(resources.Nodes), "Should not have any nodes")
assert.Equal(t, 5, len(resources.Resources), "Should have 5 controllers")
for _, controllers := range resources.Resources {
for _, ctrl := range controllers {
expectedNames[ctrl.ObjectMeta.GetName()] = true
}
}
for name, val := range expectedNames {
assert.Equal(t, true, val, name)
}
}
})
}
}
+118
View File
@@ -0,0 +1,118 @@
package mutation
import (
"bufio"
"encoding/json"
"fmt"
"strings"
jsonpatchV5 "github.com/evanphx/json-patch/v5"
"github.com/fairwindsops/polaris/pkg/config"
"github.com/fairwindsops/polaris/pkg/kube"
"github.com/fairwindsops/polaris/pkg/validator"
"github.com/thoas/go-funk"
"gomodules.xyz/jsonpatch/v2"
)
// ApplyAllSchemaMutations applies available mutation to a single resource
func ApplyAllSchemaMutations(conf *config.Configuration, resourceProvider *kube.ResourceProvider, resource kube.GenericResource, mutations []jsonpatch.Operation) (kube.GenericResource, error) {
resByte := resource.OriginalObjectJSON
var jsonByte []byte
mutationByte, err := json.Marshal(mutations)
if err != nil {
return resource, err
}
patch, err := jsonpatchV5.DecodePatch(mutationByte)
if err != nil {
return resource, err
}
jsonByte, err = patch.ApplyWithOptions(resByte, &jsonpatchV5.ApplyOptions{
AllowMissingPathOnRemove: true,
EnsurePathExistsOnAdd: true,
})
if err != nil {
return resource, err
}
mutated, err := kube.NewGenericResourceFromBytes(jsonByte)
if err != nil {
return resource, err
}
return mutated, nil
}
// GetMutationsAndCommentsFromResults returns all mutations from results
func GetMutationsAndCommentsFromResults(results []validator.Result) ([]config.MutationComment, map[string][]jsonpatch.Operation) {
allMutationsFromResults := make(map[string][]jsonpatch.Operation)
comments := []config.MutationComment{}
for _, result := range results {
key := fmt.Sprintf("%s/%s/%s", result.Kind, result.Name, result.Namespace)
mutations, resultsComments := GetMutationsAndCommentsFromResult(&result)
allMutationsFromResults[key] = mutations
comments = append(comments, resultsComments...)
}
return comments, allMutationsFromResults
}
// GetMutationsAndCommentsFromResult returns all mutations from single result
func GetMutationsAndCommentsFromResult(result *validator.Result) ([]jsonpatch.Operation, []config.MutationComment) {
mutations := []jsonpatch.Operation{}
comments := []config.MutationComment{}
for _, resultMessage := range result.Results {
if len(resultMessage.Mutations) > 0 {
mutations = append(mutations, resultMessage.Mutations...)
}
if len(resultMessage.Comments) > 0 {
comments = append(comments, resultMessage.Comments...)
}
}
for _, resultMessage := range result.PodResult.Results {
if len(resultMessage.Mutations) > 0 {
mutations = append(mutations, resultMessage.Mutations...)
}
if len(resultMessage.Comments) > 0 {
comments = append(comments, resultMessage.Comments...)
}
}
for _, containerResult := range result.PodResult.ContainerResults {
for _, resultMessage := range containerResult.Results {
if len(resultMessage.Mutations) > 0 {
mutations = append(mutations, resultMessage.Mutations...)
}
if len(resultMessage.Comments) > 0 {
comments = append(comments, resultMessage.Comments...)
}
}
}
return mutations, comments
}
// UpdateMutatedContentWithComments Updates mutated object with comments
func UpdateMutatedContentWithComments(yamlContent string, comments []config.MutationComment) string {
var lines []string
scanner := bufio.NewScanner(strings.NewReader(yamlContent))
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
line := scanner.Text()
lines = append(lines, line)
}
commentMap := funk.Map(comments, func(c config.MutationComment) (string, string) {
return c.Find, c.Comment
}).(map[string]string)
fileContent := ""
for _, line := range lines {
comment, ok := commentMap[strings.TrimSpace(line)]
if ok {
line += (" #" + comment)
}
fileContent += line
fileContent += "\n"
}
return fileContent
}
+2 -2
View File
@@ -33,7 +33,7 @@ func TestValidatePDB(t *testing.T) {
},
}
pdb := unstructured.Unstructured{}
res, err := kube.NewGenericResourceFromUnstructured(pdb)
res, err := kube.NewGenericResourceFromUnstructured(pdb, nil)
res.Kind = "PodDisruptionBudget"
actualResult, err := applyNonControllerSchemaChecks(&c, nil, res)
@@ -70,7 +70,7 @@ func TestValidateIngress(t *testing.T) {
if err != nil {
panic(err)
}
res, err := kube.NewGenericResourceFromUnstructured(unst)
res, err := kube.NewGenericResourceFromUnstructured(unst, nil)
if err != nil {
panic(err)
}
+14
View File
@@ -1,3 +1,17 @@
// Copyright 2022 FairwindsOps, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validator
import (
+14
View File
@@ -1,3 +1,17 @@
// Copyright 2022 FairwindsOps, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validator
import (
+46 -9
View File
@@ -16,10 +16,12 @@ package validator
import (
"fmt"
"strings"
"time"
"github.com/fatih/color"
"github.com/thoas/go-funk"
"gomodules.xyz/jsonpatch/v2"
"github.com/fairwindsops/polaris/pkg/config"
)
@@ -52,12 +54,21 @@ type AuditData struct {
Score uint
}
// RemoveSuccessfulResults remove all test that have passed.
// RemoveSuccessfulResults removes all tests that have passed
func (res AuditData) RemoveSuccessfulResults() AuditData {
resCopy := res
resCopy.Results = funk.Map(res.Results, func(auditDataResult Result) Result {
resCopy.Results = []Result{}
filteredResults := funk.Map(res.Results, func(auditDataResult Result) Result {
return auditDataResult.removeSuccessfulResults()
}).([]Result)
for _, result := range filteredResults {
if result.isNotEmpty() {
resCopy.Results = append(resCopy.Results, result)
}
}
return resCopy
}
@@ -72,17 +83,23 @@ type ClusterInfo struct {
// ResultMessage is the result of a given check
type ResultMessage struct {
ID string
Message string
Details []string
Success bool
Severity config.Severity
Category string
ID string
Message string
Details []string
Success bool
Severity config.Severity
Category string
Mutations []jsonpatch.Operation
Comments []config.MutationComment
}
// ResultSet contiains the results for a set of checks
type ResultSet map[string]ResultMessage
func (res ResultSet) isNotEmpty() bool {
return len(res) > 0
}
func (res ResultSet) removeSuccessfulResults() ResultSet {
newResults := ResultSet{}
for k, resultMessage := range res {
@@ -113,6 +130,13 @@ func (res Result) removeSuccessfulResults() Result {
return resCopy
}
func (res Result) isNotEmpty() bool {
if res.PodResult != nil {
return res.PodResult.isNotEmpty()
}
return res.Results.isNotEmpty()
}
// PodResult provides a list of validation messages for each pod.
type PodResult struct {
Name string
@@ -129,6 +153,15 @@ func (res PodResult) removeSuccessfulResults() PodResult {
return resCopy
}
func (res PodResult) isNotEmpty() bool {
for _, cr := range res.ContainerResults {
if cr.isNotEmpty() {
return true
}
}
return res.Results.isNotEmpty()
}
// ContainerResult provides a list of validation messages for each container.
type ContainerResult struct {
Name string
@@ -141,6 +174,10 @@ func (res ContainerResult) removeSuccessfulResults() ContainerResult {
return resCopy
}
func (res ContainerResult) isNotEmpty() bool {
return res.Results.isNotEmpty()
}
func fillString(id string, l int) string {
for len(id) < l {
id += " "
@@ -208,7 +245,7 @@ func (res ResultSet) GetPrettyOutput() string {
}
}
if color.NoColor {
status = status[2:] // remove emoji
status = strings.Fields(status)[1] // remove emoji
}
str += fmt.Sprintf("%s%s %s\n", indent, checkColor.Sprint(fillString(msg.ID, minIDLength-len(indent))), status)
str += fmt.Sprintf("%s %s - %s\n", indent, msg.Category, msg.Message)
@@ -0,0 +1,50 @@
// Copyright 2019 FairwindsOps Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validator
import (
"testing"
conf "github.com/fairwindsops/polaris/pkg/config"
"github.com/fairwindsops/polaris/pkg/kube"
"github.com/fairwindsops/polaris/test"
"github.com/stretchr/testify/require"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
)
func TestGetTemplateInputReturnsPolarisSubKeys(t *testing.T) {
pod := test.MockPod() // Includes a container, required by GetPodSpec
pod.Spec.NodeName = "testNodeName"
pod.ObjectMeta.Name = "testpod"
genRes, err := kube.NewGenericResourceFromPod(pod, pod)
require.NoError(t, err, "creating new generic resource from a pod")
schemaTest := schemaTestCase{
Target: conf.TargetPodSpec, // ends up being set in the case of target: PodTemplate
Resource: genRes,
}
templateInput, err := getTemplateInput(schemaTest)
require.NoError(t, err, "getting template input from a generic resource")
require.NotNil(t, templateInput)
nodeName, ok, err := unstructured.NestedString(templateInput, "Polaris", "PodSpec", "nodeName")
require.NoError(t, err, "getting Polaris.PodSpec.nodeName from template input")
require.True(t, ok, "getting Polaris.PodSpec.nodeName from template input")
require.Equal(t, "testNodeName", nodeName, "the nodeName from template output")
podName, ok, err := unstructured.NestedString(templateInput, "Polaris", "PodTemplate", "metadata", "name")
require.NoError(t, err, "getting Polaris.PodTemplate.metadata.name from template input")
require.True(t, ok, "getting Polaris.PodTemplate.metadata.name from template input")
require.Equal(t, "testpod", podName, "the pod from template input")
}
+131 -6
View File
@@ -1,14 +1,33 @@
// Copyright 2022 FairwindsOps, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validator
import (
"errors"
"fmt"
"sort"
"strconv"
"strings"
"github.com/qri-io/jsonschema"
"github.com/sirupsen/logrus"
"github.com/thoas/go-funk"
"gomodules.xyz/jsonpatch/v2"
corev1 "k8s.io/api/core/v1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"github.com/fairwindsops/polaris/pkg/config"
"github.com/fairwindsops/polaris/pkg/kube"
@@ -46,13 +65,55 @@ func resolveCheck(conf *config.Configuration, checkID string, test schemaTestCas
if !check.IsActionable(test.Target, test.Resource.Kind, test.IsInitContianer) {
return nil, nil
}
checkPtr, err := check.TemplateForResource(test.Resource.Resource.Object)
templateInput, err := getTemplateInput(test)
if err != nil {
return nil, err
}
checkPtr, err := check.TemplateForResource(templateInput)
if err != nil {
return nil, err
}
return checkPtr, nil
}
// getTemplateInput augments a schemaTestCase.Resource.Resource.Object with
// Polaris built-in variables. The result can be used as input for
// CheckSchema.TemplateForResource().
func getTemplateInput(test schemaTestCase) (map[string]interface{}, error) {
templateInput := test.Resource.Resource.Object
if templateInput == nil {
return nil, nil
}
if test.Target == config.TargetPodSpec || test.Target == config.TargetContainer {
podSpecMap, err := kube.SerializePodSpec(test.Resource.PodSpec)
if err != nil {
return nil, err
}
err = unstructured.SetNestedMap(templateInput, podSpecMap, "Polaris", "PodSpec")
if err != nil {
return nil, err
}
podTemplateMap, ok := test.Resource.PodTemplate.(map[string]interface{})
if ok {
err := unstructured.SetNestedMap(templateInput, podTemplateMap, "Polaris", "PodTemplate")
if err != nil {
return nil, err
}
}
if test.Target == config.TargetContainer {
containerMap, err := kube.SerializeContainer(test.Container)
if err != nil {
return nil, err
}
err = unstructured.SetNestedMap(templateInput, containerMap, "Polaris", "Container")
if err != nil {
return nil, err
}
}
}
return templateInput, nil
}
func makeResult(conf *config.Configuration, check *config.SchemaCheck, passes bool, issues []jsonschema.ValError) ResultMessage {
details := []string{}
for _, issue := range issues {
@@ -148,6 +209,17 @@ func applyControllerSchemaChecks(conf *config.Configuration, resourceProvider *k
}
finalResult.Results = resultSet
nonControllerResults, err := applyTopLevelSchemaChecks(conf, resourceProvider, resource, false)
if err != nil {
return finalResult, err
}
for key, val := range nonControllerResults {
if _, ok := finalResult.Results[key]; ok {
return finalResult, errors.New("Duplicate finding for check " + key)
}
finalResult.Results[key] = val
}
podRS, err := applyPodSchemaChecks(conf, resourceProvider, resource)
if err != nil {
return finalResult, err
@@ -197,7 +269,7 @@ func applyTopLevelSchemaChecks(conf *config.Configuration, resources *kube.Resou
func applyPodSchemaChecks(conf *config.Configuration, resources *kube.ResourceProvider, controller kube.GenericResource) (ResultSet, error) {
test := schemaTestCase{
Target: config.TargetPod,
Target: config.TargetPodSpec,
ResourceProvider: resources,
Resource: controller,
}
@@ -239,18 +311,37 @@ func applySchemaCheck(conf *config.Configuration, checkID string, test schemaTes
}
var passes bool
var issues []jsonschema.ValError
var prefix string
if check.SchemaTarget != "" {
if check.SchemaTarget == config.TargetPod && check.Target == config.TargetContainer {
if check.SchemaTarget == config.TargetPodSpec && check.Target == config.TargetContainer {
podCopy := *test.Resource.PodSpec
podCopy.InitContainers = []corev1.Container{}
podCopy.Containers = []corev1.Container{*test.Container}
passes, issues, err = check.CheckPod(&podCopy)
containerIndex := funk.IndexOf(test.Resource.PodSpec.Containers, func(value corev1.Container) bool {
return value.Name == test.Container.Name
})
prefix = getJSONSchemaPrefix(test.Resource.Kind)
if prefix != "" {
prefix += "/containers/" + strconv.Itoa(containerIndex)
}
passes, issues, err = check.CheckPodSpec(&podCopy)
} else {
return nil, fmt.Errorf("Unknown combination of target (%s) and schema target (%s)", check.Target, check.SchemaTarget)
}
} else if check.Target == config.TargetPod {
passes, issues, err = check.CheckPod(test.Resource.PodSpec)
} else if check.Target == config.TargetPodSpec {
passes, issues, err = check.CheckPodSpec(test.Resource.PodSpec)
prefix = getJSONSchemaPrefix(test.Resource.Kind)
} else if check.Target == config.TargetPodTemplate {
passes, issues, err = check.CheckPodTemplate(test.Resource.PodTemplate)
prefix = getJSONSchemaPrefix(test.Resource.Kind)
} else if check.Target == config.TargetContainer {
containerIndex := funk.IndexOf(test.Resource.PodSpec.Containers, func(value corev1.Container) bool {
return value.Name == test.Container.Name
})
prefix = getJSONSchemaPrefix(test.Resource.Kind)
if prefix != "" {
prefix += "/containers/" + strconv.Itoa(containerIndex)
}
passes, issues, err = check.CheckContainer(test.Container)
} else {
passes, issues, err = check.CheckObject(test.Resource.Resource.Object)
@@ -279,6 +370,17 @@ func applySchemaCheck(conf *config.Configuration, checkID string, test schemaTes
}
}
result := makeResult(conf, check, passes, issues)
if !passes {
if funk.Contains(conf.Mutations, checkID) && len(check.Mutations) > 0 {
mutations := funk.Map(check.Mutations, func(mutation jsonpatch.Operation) jsonpatch.Operation {
mutationCopy := deepCopyMutation(mutation)
mutationCopy.Path = prefix + mutationCopy.Path
return mutationCopy
}).([]jsonpatch.Operation)
result.Mutations = mutations
result.Comments = check.Comments
}
}
return &result, nil
}
@@ -290,3 +392,26 @@ func getSortedKeys(m map[string]config.Severity) []string {
sort.Strings(keys)
return keys
}
func deepCopyMutation(source jsonpatch.Operation) jsonpatch.Operation {
destination := jsonpatch.Operation{
Operation: source.Operation,
Path: source.Path,
Value: source.Value,
}
return destination
}
func getJSONSchemaPrefix(kind string) (prefix string) {
if kind == "CronJob" {
prefix = "/spec/jobTemplate/spec/template/spec"
} else if kind == "Pod" {
prefix = "/spec"
} else if (kind == "Deployment") || (kind == "DaemonSet") ||
(kind == "StatefulSet") || (kind == "Job") || (kind == "ReplicationController") {
prefix = "/spec/template/spec"
} else {
logrus.Warningf("Mutation for this this resource (%s) is not supported", kind)
}
return prefix
}
+14
View File
@@ -1,3 +1,17 @@
// Copyright 2022 FairwindsOps, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validator
import (
+14
View File
@@ -1,3 +1,17 @@
// Copyright 2022 FairwindsOps, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package validator
import (
+66
View File
@@ -0,0 +1,66 @@
// Copyright 2022 FairwindsOps Inc
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package webhook
import (
"context"
"github.com/fairwindsops/polaris/pkg/config"
"github.com/fairwindsops/polaris/pkg/mutation"
"github.com/sirupsen/logrus"
"gomodules.xyz/jsonpatch/v2"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)
// Mutator mutate k8s resources.
type Mutator struct {
Client client.Client
Config config.Configuration
decoder *admission.Decoder
}
var _ admission.Handler = &Mutator{}
// NewMutateWebhook creates a mutating admission webhook for the apiType.
func NewMutateWebhook(mgr manager.Manager, mutator Mutator) {
path := "/mutate"
mgr.GetWebhookServer().Register(path, &webhook.Admission{Handler: &mutator})
}
func (m *Mutator) mutate(req admission.Request) ([]jsonpatch.Operation, error) {
results, err := GetValidatedResults(req.AdmissionRequest.Kind.Kind, m.decoder, req, m.Config)
if err != nil {
return nil, err
}
patches, _ := mutation.GetMutationsAndCommentsFromResult(results)
return patches, nil
}
// Handle for Validator to run validation checks.
func (m *Mutator) Handle(ctx context.Context, req admission.Request) admission.Response {
logrus.Info("Starting request")
patches, err := m.mutate(req)
if err != nil {
return admission.Errored(403, err)
}
if patches == nil {
return admission.Allowed("Allowed")
}
return admission.Patched("", patches...)
}
+10 -5
View File
@@ -47,19 +47,24 @@ func (v *Validator) InjectDecoder(d *admission.Decoder) error {
var _ admission.Handler = &Validator{}
// NewWebhook creates a validating admission webhook for the apiType.
func NewWebhook(mgr manager.Manager, validator Validator) {
// NewValidateWebhook creates a validating admission webhook for the apiType.
func NewValidateWebhook(mgr manager.Manager, validator Validator) {
path := "/validate"
mgr.GetWebhookServer().Register(path, &webhook.Admission{Handler: &validator})
}
func (v *Validator) handleInternal(req admission.Request) (*validator.Result, error) {
return GetValidatedResults(req.AdmissionRequest.Kind.Kind, v.decoder, req, v.Config)
}
// GetValidatedResults returns the validated results.
func GetValidatedResults(kind string, decoder *admission.Decoder, req admission.Request, config config.Configuration) (*validator.Result, error) {
var controller kube.GenericResource
var err error
if req.AdmissionRequest.Kind.Kind == "Pod" {
if kind == "Pod" {
pod := corev1.Pod{}
err := v.decoder.Decode(req, &pod)
err := decoder.Decode(req, &pod)
if err != nil {
return nil, err
}
@@ -75,7 +80,7 @@ func (v *Validator) handleInternal(req admission.Request) (*validator.Result, er
return nil, err
}
// TODO: consider enabling multi-resource checks
controllerResult, err := validator.ApplyAllSchemaChecks(&v.Config, nil, controller)
controllerResult, err := validator.ApplyAllSchemaChecks(&config, nil, controller)
if err != nil {
return nil, err
}
@@ -0,0 +1,19 @@
# This fails because automounting is true for both the pod and ServiceAccount.
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
automountServiceAccountToken: true
serviceAccountName: test
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: test
automountServiceAccountToken: true
@@ -0,0 +1,19 @@
# This fails because automounting is true for the pod, overriding the ServiceAccount.
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
automountServiceAccountToken: true
serviceAccountName: test
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: test
automountServiceAccountToken: false
@@ -0,0 +1,17 @@
# This fails because automounting is not disabled anywhere.
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
serviceAccountName: test
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: test
@@ -0,0 +1,19 @@
# This succeeds because automounting is disabled at the pod.
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
automountServiceAccountToken: false
serviceAccountName: test
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: test
@@ -0,0 +1,19 @@
# This succeeds because automounting is disabled at the pod and ServiceAccount.
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
automountServiceAccountToken: false
serviceAccountName: test
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: test
automountServiceAccountToken: false
@@ -0,0 +1,19 @@
# This succeeds because automounting is disabled at the pod, overriding the ServiceAccount.
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
automountServiceAccountToken: false
serviceAccountName: test
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: test
automountServiceAccountToken: true
@@ -0,0 +1,18 @@
# This succeeds because automounting is disabled at the ServiceAccount.
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
serviceAccountName: test
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: test
automountServiceAccountToken: false
+14
View File
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Pod
metadata:
labels:
app.kubernetes.io/name: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
resources:
limits:
cpu: 100m #TODO: Set this to the maximum amount of CPU you want your workload to use
memory: 128Mi
+1 -1
View File
@@ -10,5 +10,5 @@ spec:
image: nginx
resources:
limits:
memory: 256Mi
memory: 128Mi
cpu: 100m
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Pod
metadata:
labels:
app.kubernetes.io/name: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
resources:
requests:
cpu: 100m #TODO: Set this to the amount of CPU you want to reserve for your workload
memory: 128Mi
+1 -1
View File
@@ -10,5 +10,5 @@ spec:
image: nginx
resources:
requests:
memory: 256Mi
memory: 128Mi
cpu: 100m
@@ -6,9 +6,9 @@ metadata:
app.kubernetes.io/name: nginx
spec:
containers:
- name: nginx
- name: nginx
image: nginx
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_ADMIN
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Pod
metadata:
labels:
app.kubernetes.io/name: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
resources: {}
securityContext: {}
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Deployment
metadata:
labels:
env: test
name: nginx
spec:
replicas: 3
template:
spec:
containers: []
@@ -8,5 +8,4 @@ spec:
replicas: 3
template:
spec:
containers: []
containers: []
+11
View File
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
labels:
app.kubernetes.io/name: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
resources: {}
+1 -2
View File
@@ -8,5 +8,4 @@ spec:
hostIPC: false
containers:
- name: nginx
image: nginx
image: nginx
+11
View File
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
labels:
app.kubernetes.io/name: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
resources: {}
+11
View File
@@ -0,0 +1,11 @@
apiVersion: v1
kind: Pod
metadata:
labels:
app.kubernetes.io/name: nginx
name: nginx
spec:
containers:
- image: nginx
name: nginx
resources: {}
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Pod
metadata:
labels:
env: test
name: nginx
spec:
containers:
- image: nginx
name: nginx
resources: {}
securityContext:
capabilities:
drop:
- ALL
@@ -0,0 +1,15 @@
apiVersion: v1
kind: Pod
metadata:
labels:
env: test
name: nginx
spec:
containers:
- image: nginx
name: nginx
resources: {}
securityContext:
capabilities:
drop:
- ALL
@@ -0,0 +1,18 @@
# This fails because the annotation names do not match the containers.
apiVersion: v1
kind: Pod
metadata:
name: test-pod
annotations:
container.apparmor.security.beta.kubernetes.io/container1: runtime/default
container.apparmor.security.beta.kubernetes.io/container2: runtime/default
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
- name: nginx2
image: nginx
ports:
- containerPort: 81
@@ -0,0 +1,17 @@
# This fails because ALL capabilities are also added.
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: nginx
image: nginx
securityContext:
capabilities:
drop:
- ALL
add:
- all
ports:
- containerPort: 80

Some files were not shown because too many files have changed in this diff Show More