Compare commits

..

151 Commits

Author SHA1 Message Date
David Wertenteil
af8e786ab5 Merge pull request #914 from kubescape/dev
Closing issues
2022-11-16 10:59:59 +02:00
David Wertenteil
4f5839870b Merge pull request #920 from amirmalka/dev
Fixed docker build to support ARM #919
2022-11-15 14:53:20 +02:00
Amir Malka
c0d7f51d6c test build flow 2022-11-15 13:29:35 +02:00
Amir Malka
a81d770360 fixed docker build to support arm 2022-11-15 10:57:29 +02:00
David Wertenteil
17a2547f18 Merge pull request #915 from kubescape/change-test-control-name
replace control 0006 by 0048
2022-11-14 14:56:34 +02:00
David Wertenteil
87a5cd66c8 replace control 0006 by 0048 2022-11-14 14:36:37 +02:00
David Wertenteil
9436ace64f continue when resource not found 2022-11-14 13:52:46 +02:00
David Wertenteil
fde00f6bd8 Merge pull request #909 from suhasgumma/dev
pretty-print Controls format  made Pretty
2022-11-13 17:04:46 +02:00
David Wertenteil
04a72a069a Merge pull request #913 from dwertent/ignore-missing-resource
Do not exit on error
2022-11-13 16:04:15 +02:00
David Wertenteil
e2dcb5bc15 Merge pull request #912 from dwertent/dep-rbac-submit
Deprecate rbac submit
2022-11-13 16:03:51 +02:00
suhasgumma
c7040a257c Pretty Print frameworks and exceptions 2022-11-13 19:29:26 +05:30
suhasgumma
602dc00c65 Shift GetControlLink to cautils 2022-11-13 19:09:30 +05:30
David Wertenteil
0339691571 Merge pull request #911 from dwertent/adding-remidiation
Adding remediation
2022-11-13 15:12:21 +02:00
David Wertenteil
9e1f3ec131 remove from smoke test 2022-11-13 15:10:05 +02:00
David Wertenteil
b8589819dc Do not exit on error 2022-11-13 15:06:32 +02:00
David Wertenteil
a3e87f4c01 Updating json v1 deprecation message 2022-11-13 15:03:22 +02:00
David Wertenteil
21ab5a602e Deprecate rbac submit 2022-11-13 15:01:32 +02:00
David Wertenteil
5d97d7b4b2 adding Remediation to message 2022-11-13 14:55:52 +02:00
suhasgumma
d8d7d0b372 Updated and Used GetControlLink 2022-11-13 17:56:39 +05:30
suhasgumma
b8323d41fc Modified Link Convention for CIS Controls 2022-11-13 17:22:37 +05:30
suhasgumma
d0b5314201 Improve Code Quality 2022-11-13 15:39:04 +05:30
suhasgumma
547e36e73f Pretty Print Controls made Pretty 2022-11-13 14:29:30 +05:30
David Wertenteil
e593a772cb Merge pull request #908 from Moshe-Rappaport-CA/update-k8s-interface-version
Update k8s-interface version and rbac-utils
2022-11-13 09:31:00 +02:00
Moshe-Rappaport-CA
4da09529b6 Update rbac-utils tag 2022-11-10 18:56:28 +02:00
Moshe-Rappaport-CA
de375992e8 Fix go.mod in httphandler 2022-11-10 17:54:44 +02:00
Moshe-Rappaport-CA
0bc4a29881 Update k8s-interface version 2022-11-10 17:38:32 +02:00
David Wertenteil
9575c92713 Merge pull request #906 from suhasgumma/dev
Fixed: Empty Lines before printing Controls and Added Invalid Format Error
2022-11-10 11:27:22 +02:00
David Wertenteil
cf277874eb Merge pull request #907 from matthyx/ioutil
remove deprecated ioutil package
2022-11-10 11:23:10 +02:00
Matthias Bertschy
746e060402 remove deprecated ioutil package 2022-11-10 09:58:07 +01:00
suhasgumma
dd3a7c816e Invalid Format Error 2022-11-10 11:57:57 +05:30
suhasgumma
814bc3ab2c Solved: Empty Lines before printing Controls 2022-11-10 11:17:48 +05:30
David Wertenteil
dbaf6761df Merge pull request #905 from matthyx/900
900
2022-11-10 06:52:34 +02:00
Matthias Bertschy
580e45827d add IDs to controls list, deprecate id flag 2022-11-09 22:08:04 +01:00
David Wertenteil
f3b8de9d1f fixing readme (#899) 2022-11-08 12:02:52 +02:00
David Wertenteil
fb1c728b12 Merge pull request #897 from Moshe-Rappaport-CA/fix-use-artifact-from
Fix reading frameworks from local file
2022-11-06 17:34:44 +02:00
Moshe-Rappaport-CA
6964ca0d18 Fix reading frameworks from local file 2022-11-06 17:06:27 +02:00
David Wertenteil
6e9a2f55fd Merge pull request #894 from kubescape/dev
Enhancing CLI capabilities and SARIF output
2022-11-06 15:40:00 +02:00
David Wertenteil
691fa61362 Merge pull request #896 from kubescape/revert-submit-dep
Revert submit deprecation
2022-11-06 15:06:49 +02:00
David Wertenteil
0c1eda0d08 retrieve submit flag 2022-11-03 20:33:10 +02:00
David Wertenteil
767eac2fa6 fixed indentation 2022-11-03 20:31:59 +02:00
David Wertenteil
6f651fa2d0 Merge pull request #893 from amirmalka/dev
Added line and column information when using the SARIF format
2022-11-03 15:38:33 +02:00
Amir Malka
e3362c2e3d updated go.mod 2022-11-03 14:38:07 +02:00
Amir Malka
08b8b68f9a added line and column information when using the sarif format 2022-11-03 14:08:53 +02:00
Amir Malka
daf9ca9e7f Merge pull request #825 from AvineshTripathi/feature
added adaptor
2022-11-03 12:48:23 +02:00
Amir Malka
d1024359c9 fix dependencies 2022-11-03 12:15:13 +02:00
Amir Malka
ed6070aff9 fix go.sum 2022-11-03 12:10:34 +02:00
Amir Malka
e4dbfa3534 Merge branch 'dev' into feature 2022-11-03 11:05:10 +02:00
Avinesh Tripathi
ddd2b707c0 updated go.mod 2022-11-03 14:17:53 +05:30
David Wertenteil
cd4f1077c2 Merge pull request #892 from Moshe-Rappaport-CA/dev
Add support to exceptions on repo (files) scan
2022-11-03 10:07:10 +02:00
Moshe-Rappaport-CA
b472d1cb9d Remove irrelevant code 2022-11-03 09:52:36 +02:00
David Wertenteil
922e2548f4 Merge pull request #888 from suhasgumma/dev
Inform User if something is wrong with "controls-inputs" file they provided
2022-11-03 09:38:27 +02:00
suhasgumma
45caa7c120 Adding Log in Caller Function 2022-11-03 07:35:52 +05:30
Moshe-Rappaport-CA
670ae45d62 remove --submit from msg when not submitted 2022-11-02 16:27:40 +02:00
Moshe-Rappaport-CA
05bcf018d1 Merge remote-tracking branch 'armo/dev' into dev 2022-11-02 15:02:30 +02:00
David Wertenteil
0af5d2e0bb Merge pull request #876 from Moshe-Rappaport-CA/PER-335-removing-support-for-submitting-results-without-accountid
Per 335 removing support for submitting results without accountid
2022-11-02 12:55:20 +02:00
Moshe-Rappaport-CA
eaf05fe9be Add support to exceptions on repo (files) scan 2022-11-02 12:49:14 +02:00
David Wertenteil
e97b23f345 remove platforms build 2022-11-02 12:45:18 +02:00
David Wertenteil
83a00ded3d removed log 2022-11-02 12:43:03 +02:00
Avinesh Tripathi
78f81cc968 Merge branch 'dev' into feature 2022-10-31 21:56:13 +05:30
Avinesh Tripathi
5d3347b4fe Added Path variables for credentials 2022-10-31 21:54:10 +05:30
David Wertenteil
64d2ef8170 Merge pull request #887 from Moshe-Rappaport-CA/dev
Support downloading system-exception from GitHub
2022-10-30 12:57:49 +02:00
suhasgumma
7c1e360b9a Error Info Added 2022-10-28 18:25:10 +05:30
Moshe Rappaport
575d36dcde Update core/core/initutils.go
Co-authored-by: David Wertenteil <dwertent@armosec.io>
2022-10-27 18:30:06 +03:00
Moshe-Rappaport-CA
8dba8f7491 Add go sum 2022-10-27 18:25:46 +03:00
Moshe-Rappaport-CA
cc39e5b905 Fix go mod and go sum 2022-10-27 18:18:26 +03:00
Moshe-Rappaport-CA
0be7e6018f Support downloading system-exception from GitHub 2022-10-27 17:59:41 +03:00
David Wertenteil
7697e3f0c4 Merge pull request #884 from Moshe-Rappaport-CA/dev
Scanning with include or exclude namespace, is only scan namespaced scope
2022-10-26 19:04:02 +03:00
David Wertenteil
379800c49f Merge pull request #885 from vladklokun/per-519-add-sarif-printer
feat: support the SARIF output format
2022-10-26 19:02:21 +03:00
Vlad Klokun
79e2515807 feat: support the SARIF output format 2022-10-26 18:13:37 +03:00
Moshe-Rappaport-CA
342f5743e2 Fix when running with include or exclude namespace
scanning only namespaced scope
2022-10-26 16:29:55 +03:00
David Wertenteil
0e81870b85 Merge pull request #799 from itsCheithanya/master
Add update command for kubescape
2022-10-26 15:46:03 +03:00
David Wertenteil
dd7a8fd0c1 Merge pull request #883 from kubescape/dev
Minor changes
2022-10-26 13:31:04 +03:00
David Wertenteil
4277331ee2 Merge pull request #882 from dwertent/master
Update README links
2022-10-26 13:04:00 +03:00
David Wertenteil
53561a728f Merge pull request #872 from BhairaviSanskriti/dev
Added tutorial for scanning container image registry
2022-10-26 13:00:45 +03:00
David Wertenteil
d0fd8c4fe4 Merge pull request #869 from shm12/master
APIServerInfo resource added to the scan
2022-10-26 12:59:51 +03:00
David Wertenteil
398989510b Merge pull request #881 from YiscahLevySilas1/dev
update hostsensor version
2022-10-26 12:56:55 +03:00
Amir Malka
f8e3ad5685 Merge pull request #845 from mrueg/Yamlv3
Upgrade to gopkg.in/yaml.v3
2022-10-26 12:56:31 +03:00
Moshe-Rappaport-CA
fbea7ef874 Merge remote-tracking branch 'armo/dev' into dev 2022-10-26 12:11:42 +03:00
YiscahLevySilas1
dc2c6f8a21 update hostsensor version 2022-10-26 11:40:28 +03:00
Amir Malka
5ee08583b6 Merge pull request #880 from amirmalka/dev
commented out tests which made actual http calls
2022-10-25 18:45:38 +03:00
Amir Malka
bfbd278e7c commented out tests which made actual http calls 2022-10-25 18:26:07 +03:00
David Wertenteil
4c6e5903e3 Adding links to readme 2022-10-25 09:49:43 +03:00
David Wertenteil
a7cd5672c1 Merge remote-tracking branch 'armosec/dev' 2022-10-24 17:23:41 +03:00
David Wertenteil
3373b728b7 Merge pull request #877 from kubescape/dev
Enhance configuration usage
2022-10-24 12:00:27 +03:00
David Wertenteil
22521b7159 use os path join in build file 2022-10-24 11:39:37 +03:00
David Wertenteil
e5fb14138e adding github token 2022-10-23 20:48:36 +03:00
David Wertenteil
1b2242330c comment out image release 2022-10-23 20:35:13 +03:00
David Wertenteil
356958cc55 Merge branch 'dev' of https://github.com/kubescape/kubescape into dev 2022-10-23 20:30:18 +03:00
Moshe Rappaport
8f1da32001 Store default URLs in cache (#875) 2022-10-23 20:29:25 +03:00
Moshe-Rappaport-CA
686352a397 PER-335 Fix comments 2022-10-23 16:54:16 +03:00
Moshe-Rappaport-CA
ef79c42ebc PER-335 Add comment 2022-10-23 16:25:47 +03:00
Moshe-Rappaport-CA
c8fc5378c1 PER-335 Remove submit option from kubescape docs 2022-10-23 16:19:38 +03:00
David Wertenteil
c296666d8e removed path from dockerfile 2022-10-23 16:00:10 +03:00
Moshe-Rappaport-CA
f193e260b0 Store default URLs in cache 2022-10-23 15:56:49 +03:00
Moshe-Rappaport-CA
82981a9a54 PER-335 Removing support for submitting results without accountID 2022-10-23 13:48:50 +03:00
David Wertenteil
3be54ca484 fixed typo 2022-10-23 12:35:54 +03:00
shm12
2f2c177674 Merge pull request #873 from shm12/dev
Fixed host-sensor control plane info collecting
2022-10-23 11:12:07 +03:00
shm12
1f47223918 Fixed host-sensor control plane info collecting 2022-10-23 10:46:44 +03:00
Sanskriti
eb646696a3 Update README.md
This is a video tutorial by Kunal Kushwaha on how to scan a container image registry.
2022-10-21 10:42:02 +05:30
Moshe Rappaport
7cfe5160d5 Merge pull request #871 from Moshe-Rappaport-CA/dev
Support for getting backend URLs from ENV
2022-10-20 10:44:32 +03:00
Moshe-Rappaport-CA
95135c4379 following review 2022-10-19 18:52:32 +03:00
Moshe-Rappaport-CA
7e604d6a5b Merge remote-tracking branch 'armo/dev' into dev 2022-10-19 13:29:09 +03:00
Moshe-Rappaport-CA
64ac2666f9 Support for getting backend URLs from ENV 2022-10-19 13:28:44 +03:00
Avinesh Tripathi
05b3459342 Merge branch 'dev' into feature 2022-10-19 13:44:27 +05:30
shm12
92ad5f2407 Merge pull request #868 from shm12/dev
New host sensor endpoint `controlPlaneInfo` and OPA upgrade
2022-10-18 16:14:36 +03:00
shm12
e3c60e3202 APIServerInfo resource added to the scan 2022-10-12 22:52:42 +03:00
shm12
7b5bcb05b1 Upgrade opa dependency 2022-10-12 20:51:50 +03:00
shm12
154f94a0af Added controlPlaneInfo host-sensor endpoint 2022-10-12 20:51:06 +03:00
David Wertenteil
063d3ee313 Adopt custom cluster name (#862)
* change user to ks

* update logs

* host scanner with fixed version

* testing gh actions

* testing gh actions

* Workflow call testing (#7)

* testing gh actions

* testing gh actions

* remove deps

* build multi platforms

* workflow_call testing

* adding workflow-call-testing branch name

* specify URL

* adding org name

* adding workflows

* cleaning from unused branches

* Adopt custom cluster name
2022-10-06 11:04:05 +03:00
David Wertenteil
79859d05c0 Merge remote-tracking branch 'armosec/dev' 2022-10-06 08:16:27 +03:00
David Wertenteil
acd3a94c46 Adopt custom cluster name 2022-10-06 08:15:58 +03:00
Alessio Greggi
13f09315e7 feat: add --kubeconfig flag (#858)
* feat: add --kubeconfig flag

* docs: add kubeconfig flag example
2022-10-06 08:11:42 +03:00
Manuel Rüger
890528bf14 Update go.mod 2022-10-03 21:21:31 +02:00
Manuel Rüger
e4aafcf81e Migrate to yaml.v3 2022-10-03 21:20:15 +02:00
David Wertenteil
81c3c34ab8 Use workflow_call (#859)
* change user to ks

* update logs

* host scanner with fixed version

* testing gh actions

* testing gh actions

* Workflow call testing (#7)

* testing gh actions

* testing gh actions

* remove deps

* build multi platforms

* workflow_call testing

* adding workflow-call-testing branch name

* specify URL

* adding org name

* adding workflows

* cleaning from unused branches
2022-10-03 14:36:44 +03:00
David Wertenteil
b7b83b26b5 cleaning from unused branches 2022-10-03 14:35:07 +03:00
David Wertenteil
639cd3dfae Merge branch 'master' of github.com:dwertent/kubescape 2022-10-03 13:52:44 +03:00
David Wertenteil
7cf1302e8a Workflow call testing (#7)
* testing gh actions

* testing gh actions

* remove deps

* build multi platforms

* workflow_call testing

* adding workflow-call-testing branch name

* specify URL

* adding org name

* adding workflows
2022-10-03 13:48:50 +03:00
David Wertenteil
dd5dd53a38 testing gh actions 2022-10-03 09:10:08 +03:00
David Wertenteil
7275b8eac7 testing gh actions 2022-10-03 09:09:50 +03:00
David Wertenteil
408c6fc998 Merge branch 'master' of github.com:dwertent/kubescape 2022-10-03 09:02:19 +03:00
David Wertenteil
5ce638572f update path env var 2022-10-02 23:09:24 +03:00
Cheithanya
4b98490ff9 update cmd functionality added 2022-10-02 23:29:21 +05:30
Cheithanya
6ea18ec75b update cmd functionality added 2022-10-02 23:27:39 +05:30
Ben Hirschberg
56e2ffec5c Add arch diagrams (#857)
* Publishing community meetings

* Adding architecture diagrams

* fix type

* resize diagrams

* Changing the operator diagram

Co-authored-by: Benyamin Hirschberg <59160382+BenHirschbergCa@users.noreply.github.com>
2022-10-02 20:36:59 +03:00
David Wertenteil
fa204a208a Merge branch 'dev' 2022-10-02 20:32:09 +03:00
David Wertenteil
9ab0fc593f Update python build file 2022-10-02 20:27:38 +03:00
Moshe-Rappaport-CA
3b9c454245 Merge remote-tracking branch 'armo/dev' into dev 2022-09-29 18:07:29 +03:00
David Wertenteil
a6fc7a0da0 Update logs (#854)
* change user to ks

* update logs

* host scanner with fixed version
2022-09-29 12:18:05 +03:00
David Wertenteil
0f3ce6917e Release (#844)
* Fix issue for scanning list obj

* Fix go mod in httphandler pkg

* Broken links fix in roadmap.md 

Planning, backlog, and wishlist links were not taking to the required section.

* override infoMap only if it's not nil

* improved icon of kubescape in readme

* Support scanning several files

* gramatical improvements

* docs(readme): Star → star

* Fix issues according to review

* Handle with issues  caused by updating opa-utils

* Fix scanning ListObj following reviews

* Update core/pkg/resourcehandler/filesloader.go

Co-authored-by: Vlad Klokun <vladklokun@users.noreply.github.com>

* Update completion.go

* Added fixed control input

* update go.mod

* Print chart name log when fail to generate

* Change formatting to %s

* Added resource prioritization information, raw resource will be sent on the result object

* Merging typo fixes from master (#772)

* greetings

* Update aws.sh

simplified the comment

* typo: In the title and h1 element

Their was a typo in index.html file.

* punctuation changes

* docs : added gitpod badge in readme.md

* fixed typos

* ƒ some grammar mistake is corrected inPULL_REQUEST_TEMPLATE.md file

* Updated README.md file

Added link to CONTRIBUTING.md file in a line in README.

* Added link to code of conduct file

I have added link to the code of conduct file and fixed some problems in the Readme file.

* Fixed readme

* Added alpine tag

Adding alpine tag instead of latest and removing repeating commands

* roadmap.md file is modified

* Automatically Close "Typo" labelled Issue

* build.py is modified

* modified PR template

* Fixed some typos in feature_request.md

"." at the end of the headings were missing and all the text were in same line.
Now this gives a clear and concise view of the texts.

* fixed the typo in docs/index.html

Found and fixed typo in the 'alt' attribute of img tag

* Update PULL_REQUEST_TEMPLATE.md

Co-authored-by: Krishna Agarwal <dmkrishna.agarwal@gmail.com>
Co-authored-by: Saswata Senapati <74651639+saswat16@users.noreply.github.com>
Co-authored-by: Rahul Singh <110548934+rahuldhirendersingh@users.noreply.github.com>
Co-authored-by: deepuyadav004 <deepuyadavze@gmail.com>
Co-authored-by: kartik <97971066+kartikgajjar7@users.noreply.github.com>
Co-authored-by: Rounak-28 <95576871+Rounak-28@users.noreply.github.com>
Co-authored-by: pwnb0y <vickykr07@yahoo.com>
Co-authored-by: Ben Hirschberg <59160382+slashben@users.noreply.github.com>
Co-authored-by: Saptarshi Sarkar <saptarshi.programmer@gmail.com>
Co-authored-by: Rahul Surwade <93492791+RahulSurwade08@users.noreply.github.com>
Co-authored-by: Suhas Gumma <43647369+suhasgumma@users.noreply.github.com>
Co-authored-by: Kamal Nayan <95926324+legendarykamal@users.noreply.github.com>
Co-authored-by: TarangVerma <90996971+TarangVerma@users.noreply.github.com>
Co-authored-by: avikittu <65793296+avikittu@users.noreply.github.com>

* update logger version

* update logger version (#773)

* Fixed: Kubescape fails to authenticate remote private Github repo (#721)

* grammar error fixer in CONTRIBUTING.md

* scanning private git repository is available

* giturl to gitapi

* NO TOKEN error functionality added

* Used GetToken method of giturl.IGitAPPI for auth

Co-authored-by: satyam kale <satyamkale271@gmail.com>
Co-authored-by: Ben Hirschberg <59160382+slashben@users.noreply.github.com>

* bump opa-utils to 181

* Option to force enable color output (closes #560) (#767)

* Option to force enable color output (closes #560)

(cherry picked from commit 4f951781ee8dd6bb451ac7d159787f47e4b07379)

* Update go.mod

* update scanner image

* Update host scanner image  (#774)

* update logger version

* update scanner image

* remove windows exe extension

* Remove windows extension build (#775)

* update logger version

* update scanner image

* remove windows exe extension

* commened out prioritization logic

* Edit Junit output (#802)

* Edit Junit output

* Update go sum

* Following review

* update AdoptClusterName

* Print line separator only if some controls failed (#813)

* removed the extra 'download' word from the example (#810)

it was confusing to understand the download command because there was an extra 'download' mentioned

* Prioritization (#815)

* removed commented out code

* Added attack tracks information to prioritization algorithm

* bump opa-utils

* go mod tidy

* go mod tidy

* CR changes

* Issue 613 cluster name (#783)

* added --clusterName flag (#613)

Signed-off-by: Anubhav Gupta <mail.anubhav06@gmail.com>

* update flag name to --cluster-name

Signed-off-by: Anubhav Gupta <mail.anubhav06@gmail.com>

Signed-off-by: Anubhav Gupta <mail.anubhav06@gmail.com>

* Per 307 fail on severity counters (#831)

* feat: fail on exceeding severity thresholds (#830)

- Add support for severity counters
- Add support for CLI flags that set severity thresholds
- Terminate Kubescape with an exit code 1 if scan results exceed the
  severity thresholds

* Update opa-utils pkg version

Co-authored-by: Vlad Klokun <vladklokun@users.noreply.github.com>

* Fix merge conflict

* typo in .gitignore file (#833)

* remove unsupported installation method

* fixed welcome message

* fixed merge

* fixed attack tracks loading logic

* add flag validation for --account-id (#605) (#793)

* add flag validation for --account-id (#605)

Signed-off-by: Anubhav Gupta <mail.anubhav06@gmail.com>

* add flag validation for --client-id & --secret-key

Signed-off-by: Anubhav Gupta <mail.anubhav06@gmail.com>

* Validation method should be a member function

* Adding unit tests for credentials validate

Signed-off-by: Anubhav Gupta <mail.anubhav06@gmail.com>
Co-authored-by: David Wertenteil <dwertent@armosec.io>

* Scan Kustomize Directory (#795)

* Scan Kustomize Files

* update 'scam Kustomize Directory' documentation in  Readme.md

* go get

* go get inside httphandler

* SourceTypeKustomizeDirectory

* Added Scan for Kustomization File

Co-authored-by: David Wertenteil <dwertent@armosec.io>

* feat: unify severity threshold into one CLI flag (#838)

* feat: unify severity threshold into one CLI flag

Before this commit, severity threshold flags were separated by severity.
This commit unifies these thresholds into one flag that forces Kubescape
to terminate with an exit code 1 if there was at least one failed
control at the specified severity threshold or above.

* chore: update opa utils version

* chore: update opa-utils in httphandler

* feat: dont enforce severity by default

Previous iteration of supporting the severity threshold enforced it even
if the severity threshold was not explicitly specified.
This change enforces the severity threshold only if it has been
explicitly set.

* refactor: clarify flagValidationFramework func name

This change clarifies the meaning of the function that validates the
scan info for the `scan framework` command.
It achieves this by renaming the `flagValidationFramework` function to
`validateFrameworkScanInfo`.

* Merge branch 'master' into dev

Signed-off-by: Anubhav Gupta <mail.anubhav06@gmail.com>
Co-authored-by: Moshe-Rappaport-CA <moshep@armosec.io>
Co-authored-by: Moshe Rappaport <89577611+Moshe-Rappaport-CA@users.noreply.github.com>
Co-authored-by: Om Raut <33827410+om2137@users.noreply.github.com>
Co-authored-by: Kamal Nayan <95926324+legendarykamal@users.noreply.github.com>
Co-authored-by: Vlad Klokun <vladklokun@users.noreply.github.com>
Co-authored-by: Chirag Arora <84070677+Chirag8023@users.noreply.github.com>
Co-authored-by: shm12 <shmuelb@armosec.io>
Co-authored-by: Amir Malka <amirm@armosec.io>
Co-authored-by: Krishna Agarwal <dmkrishna.agarwal@gmail.com>
Co-authored-by: Saswata Senapati <74651639+saswat16@users.noreply.github.com>
Co-authored-by: Rahul Singh <110548934+rahuldhirendersingh@users.noreply.github.com>
Co-authored-by: deepuyadav004 <deepuyadavze@gmail.com>
Co-authored-by: kartik <97971066+kartikgajjar7@users.noreply.github.com>
Co-authored-by: Rounak-28 <95576871+Rounak-28@users.noreply.github.com>
Co-authored-by: pwnb0y <vickykr07@yahoo.com>
Co-authored-by: Ben Hirschberg <59160382+slashben@users.noreply.github.com>
Co-authored-by: Saptarshi Sarkar <saptarshi.programmer@gmail.com>
Co-authored-by: Rahul Surwade <93492791+RahulSurwade08@users.noreply.github.com>
Co-authored-by: Suhas Gumma <43647369+suhasgumma@users.noreply.github.com>
Co-authored-by: TarangVerma <90996971+TarangVerma@users.noreply.github.com>
Co-authored-by: avikittu <65793296+avikittu@users.noreply.github.com>
Co-authored-by: satyam kale <satyamkale271@gmail.com>
Co-authored-by: Aditya Pratap Singh <adityapratapsingh51@gmail.com>
Co-authored-by: Ashray Shetty <ashrayshetty1999@gmail.com>
Co-authored-by: Anubhav Gupta <mail.anubhav06@gmail.com>
Co-authored-by: Meyazhagan <meyazhagan.ofcl@gmail.com>
2022-09-29 08:48:09 +03:00
Avinesh Tripathi
10fa3cb27d Merge branch 'dev' into feature 2022-09-21 23:37:55 +05:30
Avinesh Tripathi
d8f95edff5 removed getLastScanId function 2022-09-21 23:37:08 +05:30
Avinesh Tripathi
37ffe86d8b changed name and added readme 2022-09-21 23:32:16 +05:30
Avinesh Tripathi
87fdbfdcc5 fixed 2022-09-20 18:50:19 +05:30
Cheithanya
424a218860 Added the required changes 2022-09-20 17:09:02 +05:30
Cheithanya
12f81353e0 Made the required changes 2022-09-19 00:30:26 +05:30
Avinesh Tripathi
d6427f0fc8 Merge branch 'dev' into feature 2022-09-16 10:34:51 +05:30
Avinesh Tripathi
f33a6d7634 added adaptor 2022-09-16 10:20:44 +05:30
Moshe-Rappaport-CA
5a01a1a30a Print line separator only if some controls failed 2022-09-14 19:22:08 +03:00
Cheithanya
ba588b9eef Added the comments for update command 2022-09-12 21:28:55 +05:30
Cheithanya
f48b848eb6 auto pick the OS of the usersystem 2022-09-11 23:48:14 +05:30
Cheithanya
f81fd74aa3 Added the update command for kubescape 2022-09-11 18:22:18 +05:30
itsCheithanya
ad608b08e0 Merge branch 'kubescape:master' into master 2022-09-07 14:24:55 +05:30
itsCheithanya
f9e80b709a Update rootinfo.go 2022-09-07 13:42:35 +05:30
itsCheithanya
f75b62e62c Update root.go 2022-09-07 13:39:29 +05:30
itsCheithanya
1c24a55d4b Delete kubeconfig.go 2022-09-07 13:37:32 +05:30
itsCheithanya
03418299b8 Rename kubeconfig to kubeconfig.go 2022-09-06 18:32:27 +05:30
itsCheithanya
f5bd86593c Create kubeconfig 2022-09-06 18:32:00 +05:30
itsCheithanya
2af78eaab2 Delete kubeconfig 2022-09-06 18:30:16 +05:30
itsCheithanya
67cd003afe Create kubeconfig 2022-09-06 18:18:08 +05:30
itsCheithanya
0bc542f851 Update README.md 2022-09-05 22:23:40 +05:30
97 changed files with 2309 additions and 2125 deletions

80
.github/workflows/build-image.yaml vendored Normal file
View File

@@ -0,0 +1,80 @@
name: build
on:
workflow_call:
inputs:
client:
description: 'client name'
required: true
type: string
image_tag:
description: 'image tag'
required: true
type: string
image_name:
description: 'image registry and name'
required: true
type: string
cosign:
required: false
default: false
type: boolean
description: 'run cosign on released image'
support_platforms:
required: false
default: true
type: boolean
description: 'support amd64/arm64'
secrets:
QUAYIO_REGISTRY_USERNAME:
required: true
QUAYIO_REGISTRY_PASSWORD:
required: true
jobs:
build-image:
name: Build image and upload to registry
runs-on: ubuntu-latest
permissions:
id-token: write
packages: write
contents: read
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Quay.io
env:
QUAY_PASSWORD: ${{ secrets.QUAYIO_REGISTRY_PASSWORD }}
QUAY_USERNAME: ${{ secrets.QUAYIO_REGISTRY_USERNAME }}
run: docker login -u="${QUAY_USERNAME}" -p="${QUAY_PASSWORD}" quay.io
- name: Build and push image
if: ${{ inputs.support_platforms }}
run: docker buildx build . --file build/Dockerfile --tag ${{ inputs.image_name }}:${{ inputs.image_tag }} --tag ${{ inputs.image_name }}:latest --build-arg image_version=${{ inputs.image_tag }} --build-arg client=${{ inputs.client }} --push --platform linux/amd64,linux/arm64
- name: Build and push image without amd64/arm64 support
if: ${{ !inputs.support_platforms }}
run: docker buildx build . --file build/Dockerfile --tag ${{ inputs.image_name }}:${{ inputs.image_tag }} --tag ${{ inputs.image_name }}:latest --build-arg image_version=${{ inputs.image_tag }} --build-arg client=${{ inputs.client }} --push
- name: Install cosign
uses: sigstore/cosign-installer@main
with:
cosign-release: 'v1.12.0'
- name: sign kubescape container image
if: ${{ inputs.cosign }}
env:
COSIGN_EXPERIMENTAL: "true"
run: |
cosign sign --force ${{ inputs.image_name }}:latest
cosign sign --force ${{ inputs.image_name }}:${{ inputs.image_tag }}

View File

@@ -7,26 +7,26 @@ on:
# Do not run the pipeline if only Markdown files changed
- '**.md'
jobs:
once:
name: Create release
runs-on: ubuntu-latest
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
steps:
- name: Create a release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: v2.0.${{ github.run_number }}
release_name: Release v2.0.${{ github.run_number }}
draft: false
prerelease: false
build:
name: Create cross-platform release build, tag and upload binaries
needs: once
test:
uses: ./.github/workflows/test.yaml
with:
release: "v2.0.${{ github.run_number }}"
client: test
create-release:
uses: ./.github/workflows/release.yaml
needs: test
with:
release_name: "Release v2.0.${{ github.run_number }}"
tag_name: "v2.0.${{ github.run_number }}"
secrets: inherit
publish-artifacts:
name: Build and publish artifacts
needs: create-release
runs-on: ${{ matrix.os }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
@@ -34,40 +34,7 @@ jobs:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Cache Go modules (Linux)
if: matrix.os == 'ubuntu-latest'
uses: actions/cache@v3
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Cache Go modules (macOS)
if: matrix.os == 'macos-latest'
uses: actions/cache@v3
with:
path: |
~/Library/Caches/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Cache Go modules (Windows)
if: matrix.os == 'windows-latest'
uses: actions/cache@v3
with:
path: |
~\AppData\Local\go-build
~\go\pkg\mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Set up Go
uses: actions/setup-go@v3
with:
@@ -82,34 +49,20 @@ jobs:
run: make libgit2
if: matrix.os != 'windows-latest'
- name: Test core pkg
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: go test -tags=static -v ./...
- name: Test httphandler pkg
run: cd httphandler && go test -tags=static -v ./...
- name: Build
env:
RELEASE: v2.0.${{ github.run_number }}
CLIENT: release
CGO_ENABLED: 1
run: python3 --version && python3 build.py
- name: Smoke Testing
env:
RELEASE: v2.0.${{ github.run_number }}
KUBESCAPE_SKIP_UPDATE_CHECK: "true"
run: python3 smoke_testing/init.py ${PWD}/build/${{ matrix.os }}/kubescape
- name: Upload release binaries
id: upload-release-asset
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.once.outputs.upload_url }}
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: build/${{ matrix.os }}/kubescape
asset_name: kubescape-${{ matrix.os }}
asset_content_type: application/octet-stream
@@ -120,56 +73,19 @@ jobs:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.once.outputs.upload_url }}
upload_url: ${{ needs.create-release.outputs.upload_url }}
asset_path: build/${{ matrix.os }}/kubescape.sha256
asset_name: kubescape-${{ matrix.os }}-sha256
asset_content_type: application/octet-stream
build-docker:
name: Build docker container, tag and upload to registry
needs: build
runs-on: ubuntu-latest
publish-image:
if: ${{ github.repository == 'kubescape/kubescape' }} # TODO
permissions:
id-token: write
packages: write
contents: read
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Set image version
id: image-version
run: echo '::set-output name=IMAGE_VERSION::v2.0.${{ github.run_number }}'
- name: Set image name
id: image-name
run: echo '::set-output name=IMAGE_NAME::quay.io/${{ github.repository_owner }}/kubescape'
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Quay.io
env:
QUAY_PASSWORD: ${{ secrets.QUAYIO_REGISTRY_PASSWORD }}
QUAY_USERNAME: ${{ secrets.QUAYIO_REGISTRY_USERNAME }}
run: docker login -u="${QUAY_USERNAME}" -p="${QUAY_PASSWORD}" quay.io
- name: Build the Docker image
run: docker buildx build . --file build/Dockerfile --tag ${{ steps.image-name.outputs.IMAGE_NAME }}:${{ steps.image-version.outputs.IMAGE_VERSION }} --tag ${{ steps.image-name.outputs.IMAGE_NAME }}:latest --build-arg image_version=${{ steps.image-version.outputs.IMAGE_VERSION }} --build-arg client=image-release --push --platform linux/amd64,linux/arm64
- name: Install cosign
uses: sigstore/cosign-installer@main
with:
cosign-release: 'v1.12.0'
- name: sign kubescape container image
env:
COSIGN_EXPERIMENTAL: "true"
run: |
cosign sign --force ${{ steps.image-name.outputs.IMAGE_NAME }}:latest
cosign sign --force ${{ steps.image-name.outputs.IMAGE_NAME }}:${{ steps.image-version.outputs.IMAGE_VERSION }}
uses: ./.github/workflows/build-image.yaml
needs: create-release
with:
client: "image-release"
image_name: "quay.io/${{ github.repository_owner }}/kubescape"
image_tag: "v2.0.${{ github.run_number }}"
support_platforms: true
cosign: true
secrets: inherit

View File

@@ -7,136 +7,20 @@ on:
# Do not run the pipeline if only Markdown files changed
- '**.md'
jobs:
build:
name: Create cross-platform dev build
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Cache Go modules (Linux)
if: matrix.os == 'ubuntu-latest'
uses: actions/cache@v3
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Cache Go modules (macOS)
if: matrix.os == 'macos-latest'
uses: actions/cache@v3
with:
path: |
~/Library/Caches/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Cache Go modules (Windows)
if: matrix.os == 'windows-latest'
uses: actions/cache@v3
with:
path: |
~\AppData\Local\go-build
~\go\pkg\mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.18
# - name: Test cmd pkg
# run: cd cmd && go test -v ./...
# - name: Test core pkg
# env:
# GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# run: cd core && go test -v ./...
# - name: Test cmd pkg
# run: cd cmd && go test -v ./...
- name: Install MSYS2 & libgit2 (Windows)
shell: cmd
run: .\build.bat all
if: matrix.os == 'windows-latest'
- name: Install libgit2 (Linux/macOS)
run: make libgit2
if: matrix.os != 'windows-latest'
- name: Test core pkg
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: go test -tags=static -v ./...
- name: Test httphandler pkg
run: cd httphandler && go test -tags=static -v ./...
- name: Build
env:
RELEASE: v2.0.${{ github.run_number }}
CLIENT: release-dev
CGO_ENABLED: 1
run: python3 --version && python3 build.py
- name: Smoke Testing
env:
RELEASE: v2.0.${{ github.run_number }}
KUBESCAPE_SKIP_UPDATE_CHECK: "true"
run: python3 smoke_testing/init.py ${PWD}/build/${{ matrix.os }}/kubescape
- name: Upload build artifacts
uses: actions/upload-artifact@v2
with:
name: kubescape-${{ matrix.os }}
path: build/${{ matrix.os }}/kubescape
build-docker:
name: Build docker container, tag and upload to registry
needs: build
test:
uses: ./.github/workflows/test.yaml
with:
release: "v2.0.${{ github.run_number }}"
client: test
publish-dev-image:
if: ${{ github.repository == 'kubescape/kubescape' }} # TODO
runs-on: ubuntu-latest
permissions:
id-token: write
packages: write
contents: read
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Set image version
id: image-version
run: echo '::set-output name=IMAGE_VERSION::dev-v2.0.${{ github.run_number }}'
- name: Set image name
id: image-name
run: echo '::set-output name=IMAGE_NAME::quay.io/${{ github.repository_owner }}/kubescape'
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Quay.io
env:
QUAY_PASSWORD: ${{ secrets.QUAYIO_REGISTRY_PASSWORD }}
QUAY_USERNAME: ${{ secrets.QUAYIO_REGISTRY_USERNAME }}
run: docker login -u="${QUAY_USERNAME}" -p="${QUAY_PASSWORD}" quay.io
- name: Build the Docker image
run: docker buildx build . --file build/Dockerfile --tag ${{ steps.image-name.outputs.IMAGE_NAME }}:${{ steps.image-version.outputs.IMAGE_VERSION }} --build-arg image_version=${{ steps.image-version.outputs.IMAGE_VERSION }} --build-arg client=image-dev --push --platform linux/amd64,linux/arm64
uses: ./.github/workflows/build-image.yaml
needs: test
with:
client: "image-dev"
image_name: "quay.io/${{ github.repository_owner }}/kubescape"
image_tag: "dev-v2.0.${{ github.run_number }}"
support_platforms: true
cosign: true
secrets: inherit

View File

@@ -6,87 +6,11 @@ on:
types: [ edited, opened, synchronize, reopened ]
paths-ignore:
# Do not run the pipeline if only Markdown files changed
- '**.yaml'
- '**.md'
jobs:
build:
name: Create cross-platform build
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Cache Go modules (Linux)
if: matrix.os == 'ubuntu-latest'
uses: actions/cache@v3
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Cache Go modules (macOS)
if: matrix.os == 'macos-latest'
uses: actions/cache@v3
with:
path: |
~/Library/Caches/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Cache Go modules (Windows)
if: matrix.os == 'windows-latest'
uses: actions/cache@v3
with:
path: |
~\AppData\Local\go-build
~\go\pkg\mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.18
- name: Install MSYS2 & libgit2 (Windows)
shell: cmd
run: .\build.bat all
if: matrix.os == 'windows-latest'
- name: Install libgit2 (Linux/macOS)
run: make libgit2
if: matrix.os != 'windows-latest'
# - name: Test cmd pkg
# run: cd cmd && go test -v ./...
- name: Test core pkg
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: go test -tags=static -v ./...
- name: Test httphandler pkg
run: cd httphandler && go test -tags=static -v ./...
- name: Build
env:
RELEASE: v2.0.${{ github.run_number }}
CLIENT: test
CGO_ENABLED: 1
run: python3 --version && python3 build.py
- name: Smoke Testing
env:
RELEASE: v2.0.${{ github.run_number }}
KUBESCAPE_SKIP_UPDATE_CHECK: "true"
run: python3 smoke_testing/init.py ${PWD}/build/${{ matrix.os }}/kubescape
test:
uses: ./.github/workflows/test.yaml
with:
release: "v2.0.${{ github.run_number }}"
client: test

41
.github/workflows/release.yaml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: build
on:
workflow_call:
inputs:
release_name:
description: 'release'
required: true
type: string
tag_name:
description: 'tag'
required: true
type: string
draft:
description: 'create draft release'
required: false
type: boolean
default: false
outputs:
upload_url:
description: "The first output string"
value: ${{ jobs.release.outputs.upload_url }}
jobs:
release:
name: Create release
runs-on: ubuntu-latest
outputs:
upload_url: ${{ steps.create_release.outputs.upload_url }}
steps:
- name: Create a release
id: create_release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ inputs.tag_name }}
release_name: ${{ inputs.release_name }}
draft: ${{ inputs.draft }}
prerelease: false

93
.github/workflows/test.yaml vendored Normal file
View File

@@ -0,0 +1,93 @@
name: test
on:
workflow_call:
inputs:
release:
description: 'release'
required: true
type: string
client:
description: 'Client name'
required: true
type: string
jobs:
build:
name: Create cross-platform build
runs-on: ${{ matrix.os }}
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
strategy:
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Cache Go modules (Linux)
if: matrix.os == 'ubuntu-latest'
uses: actions/cache@v3
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Cache Go modules (macOS)
if: matrix.os == 'macos-latest'
uses: actions/cache@v3
with:
path: |
~/Library/Caches/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Cache Go modules (Windows)
if: matrix.os == 'windows-latest'
uses: actions/cache@v3
with:
path: |
~\AppData\Local\go-build
~\go\pkg\mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.18
- name: Install MSYS2 & libgit2 (Windows)
shell: cmd
run: .\build.bat all
if: matrix.os == 'windows-latest'
- name: Install libgit2 (Linux/macOS)
run: make libgit2
if: matrix.os != 'windows-latest'
- name: Test core pkg
run: go test -tags=static -v ./...
- name: Test httphandler pkg
run: cd httphandler && go test -tags=static -v ./...
- name: Build
env:
RELEASE: ${{ inputs.release }}
CLIENT: test
CGO_ENABLED: 1
run: python3 --version && python3 build.py
- name: Smoke Testing
env:
RELEASE: ${{ inputs.release }}
KUBESCAPE_SKIP_UPDATE_CHECK: "true"
run: python3 smoke_testing/init.py ${PWD}/build/${{ matrix.os }}/kubescape

View File

@@ -40,7 +40,7 @@ curl -s https://raw.githubusercontent.com/kubescape/kubescape/master/install.sh
## Run:
```sh
kubescape scan --submit --enable-host-scan --verbose
kubescape scan --enable-host-scan --verbose
```
<img src="docs/summary.png">
@@ -51,6 +51,17 @@ kubescape scan --submit --enable-host-scan --verbose
</br>
## Architecture in short
### [CLI](#kubescape-cli)
<div align="center">
<img src="docs/ks-cli-arch.png" width="300" alt="cli-diagram">
</div>
### [Operator](https://github.com/kubescape/helm-charts#readme)
<div align="center">
<img src="docs/ks-operator-arch.png" width="300" alt="operator-diagram">
</div>
### Please [star ⭐](https://github.com/kubescape/kubescape/stargazers) the repo if you want us to continue developing and improving Kubescape 😀
</br>
@@ -85,6 +96,7 @@ We hold community meetings in [Zoom](https://us02web.zoom.us/j/84020231442) on t
* [Overview](https://youtu.be/wdBkt_0Qhbg)
* [How To Secure Kubernetes Clusters With Kubescape And Armo](https://youtu.be/ZATGiDIDBQk)
* [Scan Kubernetes YAML files](https://youtu.be/Ox6DaR7_4ZI)
* [Scan container image registry](https://youtu.be/iQ_k8EnK-3s)
* [Scan Kubescape on an air-gapped environment (offline support)](https://youtu.be/IGXL9s37smM)
* [Managing exceptions in the Kubescape SaaS version](https://youtu.be/OzpvxGmCR80)
* [Configure and run customized frameworks](https://youtu.be/12Sanq_rEhs)
@@ -163,22 +175,22 @@ Or to your profile (not preferred): `nix-env --install -A nixpkgs.kubescape`
### Examples
#### Scan a running Kubernetes cluster and submit results to the [Kubescape SaaS version](https://cloud.armosec.io?utm_source=github&utm_medium=repository)
#### Scan a running Kubernetes cluster
```
kubescape scan --submit --enable-host-scan --verbose
kubescape scan --enable-host-scan --verbose
```
> Read [here](https://hub.armosec.io/docs/host-sensor?utm_source=github&utm_medium=repository) more about the `enable-host-scan` flag
#### Scan a running Kubernetes cluster with [`nsa`](https://www.nsa.gov/Press-Room/News-Highlights/Article/Article/2716980/nsa-cisa-release-kubernetes-hardening-guidance/) framework and submit results to the [Kubescape SaaS version](https://cloud.armosec.io?utm_source=github&utm_medium=repository)
#### Scan a running Kubernetes cluster with [`nsa`](https://www.nsa.gov/Press-Room/News-Highlights/Article/Article/2716980/nsa-cisa-release-kubernetes-hardening-guidance/) framework
```
kubescape scan framework nsa --submit
kubescape scan framework nsa
```
#### Scan a running Kubernetes cluster with [`MITRE ATT&CK®`](https://www.microsoft.com/security/blog/2021/03/23/secure-containerized-environments-with-updated-threat-matrix-for-kubernetes/) framework and submit results to the [Kubescape SaaS version](https://cloud.armosec.io?utm_source=github&utm_medium=repository)
#### Scan a running Kubernetes cluster with [`MITRE ATT&CK®`](https://www.microsoft.com/security/blog/2021/03/23/secure-containerized-environments-with-updated-threat-matrix-for-kubernetes/) framework
```
kubescape scan framework mitre --submit
kubescape scan framework mitre
```
@@ -187,6 +199,11 @@ kubescape scan framework mitre --submit
kubescape scan control "Privileged container"
```
#### Scan using an alternative kubeconfig file
```
kubescape scan --kubeconfig cluster.conf
```
#### Scan specific namespaces
```
kubescape scan --include-namespaces development,staging,production
@@ -197,14 +214,15 @@ kubescape scan --include-namespaces development,staging,production
kubescape scan --exclude-namespaces kube-system,kube-public
```
#### Scan local `yaml`/`json` files before deploying. [Take a look at the demonstration](https://youtu.be/Ox6DaR7_4ZI). Submit the results in case the directory is a git repo. [docs](https://hub.armosec.io/docs/repository-scanning?utm_source=github&utm_medium=repository)
#### Scan local `yaml`/`json` files before deploying. [Take a look at the demonstration](https://youtu.be/Ox6DaR7_4ZI).
```
kubescape scan *.yaml --submit
kubescape scan *.yaml
```
#### Scan Kubernetes manifest files from a git repository [and submit the results](https://hub.armosec.io/docs/repository-scanning?utm_source=github&utm_medium=repository)
#### Scan Kubernetes manifest files from a git repository
```
kubescape scan https://github.com/kubescape/kubescape --submit
kubescape scan https://github.com/kubescape/kubescape
```
#### Display all scanned resources (including the resources which passed)
@@ -251,13 +269,13 @@ kubescape scan --exceptions examples/exceptions/exclude-kube-namespaces.json
#### Scan Helm charts
```
kubescape scan </path/to/directory> --submit
kubescape scan </path/to/directory>
```
> Kubescape will load the default value file
#### Scan Kustomize Directory
```
kubescape scan </path/to/directory> --submit
kubescape scan </path/to/directory>
```
> Kubescape will generate Kubernetes Yaml Objects using 'Kustomize' file and scans them for security.

View File

@@ -14,14 +14,15 @@ def check_status(status, msg):
def get_build_dir():
current_platform = platform.system()
build_dir = "./build/"
build_dir = ""
if current_platform == "Windows": build_dir += "windows-latest"
elif current_platform == "Linux": build_dir += "ubuntu-latest"
elif current_platform == "Darwin": build_dir += "macos-latest"
if current_platform == "Windows": build_dir = "windows-latest"
elif current_platform == "Linux": build_dir = "ubuntu-latest"
elif current_platform == "Darwin": build_dir = "macos-latest"
else: raise OSError("Platform %s is not supported!" % (current_platform))
return build_dir
return os.path.join("build", build_dir)
def get_package_name():
package_name = "kubescape"
@@ -56,7 +57,7 @@ def main():
if client_name:
ldflags += " -X {}={}".format(client_var, client_name)
build_command = ["go", "build", "-tags=static", "-o", ks_file, "-ldflags" ,ldflags]
build_command = ["go", "build", "-buildmode=pie", "-tags=static", "-o", ks_file, "-ldflags" ,ldflags]
print("Building kubescape and saving here: {}".format(ks_file))
print("Build command: {}".format(" ".join(build_command)))

View File

@@ -12,7 +12,7 @@ ENV CGO_ENABLED=1
# Install required python/pip
ENV PYTHONUNBUFFERED=1
RUN apk add --update --no-cache python3 git openssl-dev musl-dev gcc make cmake pkgconfig && ln -sf python3 /usr/bin/python
RUN apk add --update --no-cache python3 gcc make git libc-dev binutils-gold cmake pkgconfig && ln -sf python3 /usr/bin/python
RUN python3 -m ensurepip
RUN pip3 install --no-cache --upgrade pip setuptools

View File

@@ -25,6 +25,9 @@ var (
# Set access key
kubescape config set secretKey <access key>
# Set cloudAPIURL
kubescape config set cloudAPIURL <cloud API URL>
`
)

View File

@@ -33,9 +33,13 @@ func getSetCmd(ks meta.IKubescape) *cobra.Command {
}
var supportConfigSet = map[string]func(*metav1.SetConfig, string){
"accountID": func(s *metav1.SetConfig, account string) { s.Account = account },
"clientID": func(s *metav1.SetConfig, clientID string) { s.ClientID = clientID },
"secretKey": func(s *metav1.SetConfig, secretKey string) { s.SecretKey = secretKey },
"accountID": func(s *metav1.SetConfig, account string) { s.Account = account },
"clientID": func(s *metav1.SetConfig, clientID string) { s.ClientID = clientID },
"secretKey": func(s *metav1.SetConfig, secretKey string) { s.SecretKey = secretKey },
"cloudAPIURL": func(s *metav1.SetConfig, cloudAPIURL string) { s.CloudAPIURL = cloudAPIURL },
"cloudAuthURL": func(s *metav1.SetConfig, cloudAuthURL string) { s.CloudAuthURL = cloudAuthURL },
"cloudReportURL": func(s *metav1.SetConfig, cloudReportURL string) { s.CloudReportURL = cloudReportURL },
"cloudUIURL": func(s *metav1.SetConfig, cloudUIURL string) { s.CloudUIURL = cloudUIURL },
}
func stringKeysToSlice(m map[string]func(*metav1.SetConfig, string)) []string {

View File

@@ -24,8 +24,8 @@ var (
# Download the NSA framework. Run 'kubescape list frameworks' for all frameworks names
kubescape download framework nsa
# Download the "Allowed hostPath" control. Run 'kubescape list controls' for all controls names
kubescape download control "Allowed hostPath"
# Download the "HostPath mount" control. Run 'kubescape list controls' for all controls names
kubescape download control "HostPath mount"
# Download the "C-0001" control. Run 'kubescape list controls --id' for all controls ids
kubescape download control C-0001

View File

@@ -20,11 +20,8 @@ var (
# List all supported frameworks names
kubescape list frameworks --account <account id>
# List all supported controls names
# List all supported controls names with ids
kubescape list controls
# List all supported controls ids
kubescape list controls --id
Control documentation:
https://hub.armosec.io/docs/controls
@@ -67,8 +64,8 @@ func GetListCmd(ks meta.IKubescape) *cobra.Command {
listCmd.PersistentFlags().StringVarP(&listPolicies.Credentials.Account, "account", "", "", "Kubescape SaaS account ID. Default will load account ID from cache")
listCmd.PersistentFlags().StringVarP(&listPolicies.Credentials.ClientID, "client-id", "", "", "Kubescape SaaS client ID. Default will load client ID from cache, read more - https://hub.armosec.io/docs/authentication")
listCmd.PersistentFlags().StringVarP(&listPolicies.Credentials.SecretKey, "secret-key", "", "", "Kubescape SaaS secret key. Default will load secret key from cache, read more - https://hub.armosec.io/docs/authentication")
listCmd.PersistentFlags().StringVar(&listPolicies.Format, "format", "pretty-print", "output format. supported: 'pretty-printer'/'json'")
listCmd.PersistentFlags().BoolVarP(&listPolicies.ListIDs, "id", "", false, "List control ID's instead of controls names")
listCmd.PersistentFlags().StringVar(&listPolicies.Format, "format", "pretty-print", "output format. supported: 'pretty-print'/'json'")
listCmd.PersistentFlags().MarkDeprecated("id", "Control ID's are included in list outpus")
return listCmd
}

View File

@@ -13,6 +13,7 @@ import (
"github.com/kubescape/kubescape/v2/cmd/list"
"github.com/kubescape/kubescape/v2/cmd/scan"
"github.com/kubescape/kubescape/v2/cmd/submit"
"github.com/kubescape/kubescape/v2/cmd/update"
"github.com/kubescape/kubescape/v2/cmd/version"
"github.com/kubescape/kubescape/v2/core/cautils"
"github.com/kubescape/kubescape/v2/core/cautils/getter"
@@ -76,6 +77,7 @@ func getRootCmd(ks meta.IKubescape) *cobra.Command {
rootCmd.AddCommand(completion.GetCompletionCmd())
rootCmd.AddCommand(version.GetVersionCmd())
rootCmd.AddCommand(config.GetConfigCmd(ks))
rootCmd.AddCommand(update.GetUpdateCmd())
return rootCmd
}

View File

@@ -23,7 +23,7 @@ var (
kubescape scan control "privileged container"
# Scan list of controls separated with a comma
kubescape scan control "privileged container","allowed hostpath"
kubescape scan control "privileged container","HostPath mount"
# Scan list of controls using the control ID separated with a comma
kubescape scan control C-0058,C-0057
@@ -61,7 +61,7 @@ func getControlCmd(ks meta.IKubescape, scanInfo *cautils.ScanInfo) *cobra.Comman
if err := validateFrameworkScanInfo(scanInfo); err != nil {
return err
}
// flagValidationControl(scanInfo)
scanInfo.PolicyIdentifier = []cautils.PolicyIdentifier{}

View File

@@ -1,6 +1,7 @@
package scan
import (
"flag"
"fmt"
"github.com/kubescape/k8s-interface/k8sinterface"
@@ -13,7 +14,7 @@ var scanCmdExamples = `
Scan command is for scanning an existing cluster or kubernetes manifest files based on pre-defined frameworks
# Scan current cluster with all frameworks
kubescape scan --submit --enable-host-scan --verbose
kubescape scan --enable-host-scan --verbose
# Scan kubernetes YAML manifest files
kubescape scan *.yaml
@@ -70,34 +71,33 @@ func GetScanCommand(ks meta.IKubescape) *cobra.Command {
scanCmd.PersistentFlags().StringVar(&scanInfo.ControlsInputs, "controls-config", "", "Path to an controls-config obj. If not set will download controls-config from ARMO management portal")
scanCmd.PersistentFlags().StringVar(&scanInfo.UseExceptions, "exceptions", "", "Path to an exceptions obj. If not set will download exceptions from ARMO management portal")
scanCmd.PersistentFlags().StringVar(&scanInfo.UseArtifactsFrom, "use-artifacts-from", "", "Load artifacts from local directory. If not used will download them")
scanCmd.PersistentFlags().StringVarP(&scanInfo.ExcludedNamespaces, "exclude-namespaces", "e", "", "Namespaces to exclude from scanning. Recommended: kube-system,kube-public")
scanCmd.PersistentFlags().StringVarP(&scanInfo.ExcludedNamespaces, "exclude-namespaces", "e", "", "Namespaces to exclude from scanning. Notice, when running with `exclude-namespace` kubescape does not scan cluster-scoped objects.")
scanCmd.PersistentFlags().Float32VarP(&scanInfo.FailThreshold, "fail-threshold", "t", 100, "Failure threshold is the percent above which the command fails and returns exit code 1")
scanCmd.PersistentFlags().StringVar(&scanInfo.FailThresholdSeverity, "severity-threshold", "", "Severity threshold is the severity of failed controls at which the command fails and returns exit code 1")
scanCmd.PersistentFlags().StringVarP(&scanInfo.Format, "format", "f", "pretty-printer", `Output format. Supported formats: "pretty-printer", "json", "junit", "prometheus", "pdf", "html"`)
scanCmd.PersistentFlags().StringVarP(&scanInfo.Format, "format", "f", "pretty-printer", `Output format. Supported formats: "pretty-printer", "json", "junit", "prometheus", "pdf", "html", "sarif"`)
scanCmd.PersistentFlags().StringVar(&scanInfo.IncludeNamespaces, "include-namespaces", "", "scan specific namespaces. e.g: --include-namespaces ns-a,ns-b")
scanCmd.PersistentFlags().BoolVarP(&scanInfo.Local, "keep-local", "", false, "If you do not want your Kubescape results reported to ARMO backend. Use this flag if you ran with the '--submit' flag in the past and you do not want to submit your current scan results")
scanCmd.PersistentFlags().BoolVarP(&scanInfo.Local, "keep-local", "", false, "If you do not want your Kubescape results reported to configured backend.")
scanCmd.PersistentFlags().StringVarP(&scanInfo.Output, "output", "o", "", "Output file. Print output to file and not stdout")
scanCmd.PersistentFlags().BoolVarP(&scanInfo.VerboseMode, "verbose", "v", false, "Display all of the input resources and not only failed resources")
scanCmd.PersistentFlags().StringVar(&scanInfo.View, "view", string(cautils.ResourceViewType), fmt.Sprintf("View results based on the %s/%s. default is --view=%s", cautils.ResourceViewType, cautils.ControlViewType, cautils.ResourceViewType))
scanCmd.PersistentFlags().BoolVar(&scanInfo.UseDefault, "use-default", false, "Load local policy object from default path. If not used will download latest")
scanCmd.PersistentFlags().StringSliceVar(&scanInfo.UseFrom, "use-from", nil, "Load local policy object from specified path. If not used will download latest")
scanCmd.PersistentFlags().BoolVarP(&scanInfo.Submit, "submit", "", false, "Send the scan results to ARMO management portal where you can see the results in a user-friendly UI, choose your preferred compliance framework, check risk results history and trends, manage exceptions, get remediation recommendations and much more. By default the results are not submitted")
scanCmd.PersistentFlags().StringVar(&scanInfo.HostSensorYamlPath, "host-scan-yaml", "", "Override default host scanner DaemonSet. Use this flag cautiously")
scanCmd.PersistentFlags().StringVar(&scanInfo.FormatVersion, "format-version", "v1", "Output object can be different between versions, this is for maintaining backward and forward compatibility. Supported:'v1'/'v2'")
scanCmd.PersistentFlags().StringVar(&scanInfo.CustomClusterName, "cluster-name", "", "Set the custom name of the cluster. Not same as the kube-context flag")
scanCmd.PersistentFlags().BoolVarP(&scanInfo.Submit, "submit", "", false, "Submit the scan results to Kubescape SaaS where you can see the results in a user-friendly UI, choose your preferred compliance framework, check risk results history and trends, manage exceptions, get remediation recommendations and much more. By default the results are not submitted")
// Deprecated flags - remove 1.May.2022
scanCmd.PersistentFlags().BoolVarP(&scanInfo.Silent, "silent", "s", false, "Silent progress messages")
scanCmd.PersistentFlags().MarkDeprecated("silent", "use '--logger' flag instead. Flag will be removed at 1.May.2022")
// hidden flags
scanCmd.PersistentFlags().MarkHidden("host-scan-yaml") // this flag should be used very cautiously. We prefer users will not use it at all unless the DaemonSet can not run pods on the nodes
scanCmd.PersistentFlags().MarkHidden("silent") // this flag should be deprecated since we added the --logger support
// scanCmd.PersistentFlags().MarkHidden("format-version") // meant for testing different output approaches and not for common use
hostF := scanCmd.PersistentFlags().VarPF(&scanInfo.HostSensorEnabled, "enable-host-scan", "", "Deploy ARMO K8s host-sensor daemonset in the scanned cluster. Deleting it right after we collecting the data. Required to collect valuable data from cluster nodes for certain controls. Yaml file: https://github.com/kubescape/kubescape/blob/master/core/pkg/hostsensorutils/hostsensor.yaml")
// Retrieve --kubeconfig flag from https://github.com/kubernetes/kubectl/blob/master/pkg/cmd/cmd.go
scanCmd.PersistentFlags().AddGoFlag(flag.Lookup("kubeconfig"))
hostF := scanCmd.PersistentFlags().VarPF(&scanInfo.HostSensorEnabled, "enable-host-scan", "", "Deploy Kubescape host-sensor daemonset in the scanned cluster. Deleting it right after we collecting the data. Required to collect valuable data from cluster nodes for certain controls. Yaml file: https://github.com/kubescape/kubescape/blob/master/core/pkg/hostsensorutils/hostsensor.yaml")
hostF.NoOptDefVal = "true"
hostF.DefValue = "false, for no TTY in stdin"

View File

@@ -31,10 +31,11 @@ var (
// getRBACCmd represents the RBAC command
func getRBACCmd(ks meta.IKubescape, submitInfo *v1.Submit) *cobra.Command {
return &cobra.Command{
Use: "rbac",
Example: rbacExamples,
Short: "Submit cluster's Role-Based Access Control(RBAC)",
Long: ``,
Use: "rbac",
Deprecated: "This command is deprecated and will not be supported after 1/Jan/2023. Please use the 'scan' command instead.",
Example: rbacExamples,
Short: "Submit cluster's Role-Based Access Control(RBAC)",
Long: ``,
RunE: func(cmd *cobra.Command, args []string) error {
if err := flagValidationSubmit(submitInfo); err != nil {

View File

@@ -7,16 +7,21 @@ import (
)
var submitCmdExamples = `
# Submit Kubescape scan results file
kubescape submit results
# Submit exceptions file to Kubescape SaaS
kubescape submit exceptions
`
func GetSubmitCmd(ks meta.IKubescape) *cobra.Command {
var submitInfo metav1.Submit
submitCmd := &cobra.Command{
Use: "submit <command>",
Short: "Submit an object to the Kubescape SaaS version",
Long: ``,
Use: "submit <command>",
Short: "Submit an object to the Kubescape SaaS version",
Long: ``,
Example: submitCmdExamples,
Run: func(cmd *cobra.Command, args []string) {
},
}

59
cmd/update/update.go Normal file
View File

@@ -0,0 +1,59 @@
package update
//This update command updates to the latest kubescape release.
//Example:-
// kubescape update
import (
"os/exec"
"runtime"
logger "github.com/kubescape/go-logger"
"github.com/kubescape/kubescape/v2/core/cautils"
"github.com/spf13/cobra"
)
func GetUpdateCmd() *cobra.Command {
updateCmd := &cobra.Command{
Use: "update",
Short: "Update your version",
Long: ``,
RunE: func(_ *cobra.Command, args []string) error {
//Checking the user's version of kubescape to the latest release
if cautils.BuildNumber == cautils.LatestReleaseVersion {
//your version == latest version
logger.L().Info(("You are in the latest version"))
} else {
const OSTYPE string = runtime.GOOS
var ShellToUse string
switch OSTYPE {
case "windows":
cautils.StartSpinner()
//run the installation command for windows
ShellToUse = "powershell"
_, err := exec.Command(ShellToUse, "-c", "iwr -useb https://raw.githubusercontent.com/kubescape/kubescape/master/install.ps1 | iex").Output()
if err != nil {
logger.L().Fatal(err.Error())
}
cautils.StopSpinner()
default:
ShellToUse = "bash"
cautils.StartSpinner()
//run the installation command for linux and macOS
_, err := exec.Command(ShellToUse, "-c", "curl -s https://raw.githubusercontent.com/kubescape/kubescape/master/install.sh | /bin/bash").Output()
if err != nil {
logger.L().Fatal(err.Error())
}
cautils.StopSpinner()
}
}
return nil
},
}
return updateCmd
}

View File

@@ -0,0 +1,12 @@
package cautils
import (
"fmt"
"strings"
)
func GetControlLink(controlID string) string {
// For CIS Controls, cis-1.1.3 will be transformed to cis-1-1-3 in documentation link.
docLinkID := strings.ReplaceAll(controlID, ".", "-")
return fmt.Sprintf("https://hub.armosec.io/docs/%s", strings.ToLower(docLinkID))
}

View File

@@ -11,6 +11,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
logger "github.com/kubescape/go-logger"
"github.com/kubescape/go-logger/helpers"
"github.com/kubescape/k8s-interface/k8sinterface"
"github.com/kubescape/kubescape/v2/core/cautils/getter"
corev1 "k8s.io/api/core/v1"
@@ -32,6 +33,10 @@ type ConfigObj struct {
Token string `json:"invitationParam,omitempty"`
CustomerAdminEMail string `json:"adminMail,omitempty"`
ClusterName string `json:"clusterName,omitempty"`
CloudReportURL string `json:"cloudReportURL,omitempty"`
CloudAPIURL string `json:"cloudAPIURL,omitempty"`
CloudUIURL string `json:"cloudUIURL,omitempty"`
CloudAuthURL string `json:"cloudAuthURL,omitempty"`
}
// Config - convert ConfigObj to config file
@@ -75,6 +80,10 @@ type ITenantConfig interface {
GetClientID() string
GetSecretKey() string
GetConfigObj() *ConfigObj
GetCloudReportURL() string
GetCloudAPIURL() string
GetCloudUIURL() string
GetCloudAuthURL() string
// GetBackendAPI() getter.IBackend
// GenerateURL()
@@ -103,10 +112,11 @@ func NewLocalConfig(
}
updateCredentials(lc.configObj, credentials)
updateCloudURLs(lc.configObj)
// If a custom cluster name is provided then set that name, else use the cluster's original name
if customClusterName != "" {
lc.configObj.ClusterName = AdoptCustomClusterName(customClusterName)
lc.configObj.ClusterName = AdoptClusterName(customClusterName)
} else if clusterName != "" {
lc.configObj.ClusterName = AdoptClusterName(clusterName) // override config clusterName
}
@@ -114,18 +124,43 @@ func NewLocalConfig(
lc.backendAPI.SetAccountID(lc.configObj.AccountID)
lc.backendAPI.SetClientID(lc.configObj.ClientID)
lc.backendAPI.SetSecretKey(lc.configObj.SecretKey)
if lc.configObj.CloudAPIURL != "" {
lc.backendAPI.SetCloudAPIURL(lc.configObj.CloudAPIURL)
} else {
lc.configObj.CloudAPIURL = lc.backendAPI.GetCloudAPIURL()
}
if lc.configObj.CloudAuthURL != "" {
lc.backendAPI.SetCloudAuthURL(lc.configObj.CloudAuthURL)
} else {
lc.configObj.CloudAuthURL = lc.backendAPI.GetCloudAuthURL()
}
if lc.configObj.CloudReportURL != "" {
lc.backendAPI.SetCloudReportURL(lc.configObj.CloudReportURL)
} else {
lc.configObj.CloudReportURL = lc.backendAPI.GetCloudReportURL()
}
if lc.configObj.CloudUIURL != "" {
lc.backendAPI.SetCloudUIURL(lc.configObj.CloudUIURL)
} else {
lc.configObj.CloudUIURL = lc.backendAPI.GetCloudUIURL()
}
logger.L().Debug("Kubescape Cloud URLs", helpers.String("api", lc.backendAPI.GetCloudAPIURL()), helpers.String("auth", lc.backendAPI.GetCloudAuthURL()), helpers.String("report", lc.backendAPI.GetCloudReportURL()), helpers.String("UI", lc.backendAPI.GetCloudUIURL()))
return lc
}
func (lc *LocalConfig) GetConfigObj() *ConfigObj { return lc.configObj }
func (lc *LocalConfig) GetTenantEmail() string { return lc.configObj.CustomerAdminEMail }
func (lc *LocalConfig) GetAccountID() string { return lc.configObj.AccountID }
func (lc *LocalConfig) GetClientID() string { return lc.configObj.ClientID }
func (lc *LocalConfig) GetSecretKey() string { return lc.configObj.SecretKey }
func (lc *LocalConfig) GetContextName() string { return lc.configObj.ClusterName }
func (lc *LocalConfig) GetToken() string { return lc.configObj.Token }
func (lc *LocalConfig) IsConfigFound() bool { return existsConfigFile() }
func (lc *LocalConfig) GetConfigObj() *ConfigObj { return lc.configObj }
func (lc *LocalConfig) GetTenantEmail() string { return lc.configObj.CustomerAdminEMail }
func (lc *LocalConfig) GetAccountID() string { return lc.configObj.AccountID }
func (lc *LocalConfig) GetClientID() string { return lc.configObj.ClientID }
func (lc *LocalConfig) GetSecretKey() string { return lc.configObj.SecretKey }
func (lc *LocalConfig) GetContextName() string { return lc.configObj.ClusterName }
func (lc *LocalConfig) GetToken() string { return lc.configObj.Token }
func (lc *LocalConfig) GetCloudReportURL() string { return lc.configObj.CloudReportURL }
func (lc *LocalConfig) GetCloudAPIURL() string { return lc.configObj.CloudAPIURL }
func (lc *LocalConfig) GetCloudUIURL() string { return lc.configObj.CloudUIURL }
func (lc *LocalConfig) GetCloudAuthURL() string { return lc.configObj.CloudAuthURL }
func (lc *LocalConfig) IsConfigFound() bool { return existsConfigFile() }
func (lc *LocalConfig) SetTenant() error {
// Kubescape Cloud tenant GUID
@@ -213,10 +248,11 @@ func NewClusterConfig(k8s *k8sinterface.KubernetesApi, backendAPI getter.IBacken
loadConfigFromFile(c.configObj)
}
updateCredentials(c.configObj, credentials)
updateCloudURLs(c.configObj)
// If a custom cluster name is provided then set that name, else use the cluster's original name
if customClusterName != "" {
c.configObj.ClusterName = AdoptCustomClusterName(customClusterName)
c.configObj.ClusterName = AdoptClusterName(customClusterName)
} else if clusterName != "" {
c.configObj.ClusterName = AdoptClusterName(clusterName) // override config clusterName
}
@@ -230,18 +266,44 @@ func NewClusterConfig(k8s *k8sinterface.KubernetesApi, backendAPI getter.IBacken
c.backendAPI.SetAccountID(c.configObj.AccountID)
c.backendAPI.SetClientID(c.configObj.ClientID)
c.backendAPI.SetSecretKey(c.configObj.SecretKey)
if c.configObj.CloudAPIURL != "" {
c.backendAPI.SetCloudAPIURL(c.configObj.CloudAPIURL)
} else {
c.configObj.CloudAPIURL = c.backendAPI.GetCloudAPIURL()
}
if c.configObj.CloudAuthURL != "" {
c.backendAPI.SetCloudAuthURL(c.configObj.CloudAuthURL)
} else {
c.configObj.CloudAuthURL = c.backendAPI.GetCloudAuthURL()
}
if c.configObj.CloudReportURL != "" {
c.backendAPI.SetCloudReportURL(c.configObj.CloudReportURL)
} else {
c.configObj.CloudReportURL = c.backendAPI.GetCloudReportURL()
}
if c.configObj.CloudUIURL != "" {
c.backendAPI.SetCloudUIURL(c.configObj.CloudUIURL)
} else {
c.configObj.CloudUIURL = c.backendAPI.GetCloudUIURL()
}
logger.L().Debug("Kubescape Cloud URLs", helpers.String("api", c.backendAPI.GetCloudAPIURL()), helpers.String("auth", c.backendAPI.GetCloudAuthURL()), helpers.String("report", c.backendAPI.GetCloudReportURL()), helpers.String("UI", c.backendAPI.GetCloudUIURL()))
return c
}
func (c *ClusterConfig) GetConfigObj() *ConfigObj { return c.configObj }
func (c *ClusterConfig) GetDefaultNS() string { return c.configMapNamespace }
func (c *ClusterConfig) GetAccountID() string { return c.configObj.AccountID }
func (c *ClusterConfig) GetClientID() string { return c.configObj.ClientID }
func (c *ClusterConfig) GetSecretKey() string { return c.configObj.SecretKey }
func (c *ClusterConfig) GetTenantEmail() string { return c.configObj.CustomerAdminEMail }
func (c *ClusterConfig) GetToken() string { return c.configObj.Token }
func (c *ClusterConfig) IsConfigFound() bool { return existsConfigFile() || c.existsConfigMap() }
func (c *ClusterConfig) GetConfigObj() *ConfigObj { return c.configObj }
func (c *ClusterConfig) GetDefaultNS() string { return c.configMapNamespace }
func (c *ClusterConfig) GetAccountID() string { return c.configObj.AccountID }
func (c *ClusterConfig) GetClientID() string { return c.configObj.ClientID }
func (c *ClusterConfig) GetSecretKey() string { return c.configObj.SecretKey }
func (c *ClusterConfig) GetTenantEmail() string { return c.configObj.CustomerAdminEMail }
func (c *ClusterConfig) GetToken() string { return c.configObj.Token }
func (c *ClusterConfig) GetCloudReportURL() string { return c.configObj.CloudReportURL }
func (c *ClusterConfig) GetCloudAPIURL() string { return c.configObj.CloudAPIURL }
func (c *ClusterConfig) GetCloudUIURL() string { return c.configObj.CloudUIURL }
func (c *ClusterConfig) GetCloudAuthURL() string { return c.configObj.CloudAuthURL }
func (c *ClusterConfig) IsConfigFound() bool { return existsConfigFile() || c.existsConfigMap() }
func (c *ClusterConfig) SetTenant() error {
@@ -474,19 +536,6 @@ func DeleteConfigFile() error {
return os.Remove(ConfigFileFullPath())
}
// To check if the custom cluster name is valid:
func AdoptCustomClusterName(customClusterName string) string {
is_alphanumeric := regexp.MustCompile(`^[a-zA-Z0-9]*$`).MatchString(customClusterName)
// Check it does not contain special-characters
if is_alphanumeric == false {
logger.L().Fatal("custom cluster name cannot contain special characters")
} else if len(customClusterName) >= 256 { // Check it contains less than 256 characters
logger.L().Fatal("custom cluster name cannot contain more than 255 characters")
}
return customClusterName
}
func AdoptClusterName(clusterName string) string {
re, err := regexp.Compile(`[^\w]+`)
if err != nil {
@@ -540,3 +589,39 @@ func updateCredentials(configObj *ConfigObj, credentials *Credentials) {
}
}
func getCloudURLsFromEnv(cloudURLs *CloudURLs) {
// load from env
if cloudAPIURL := os.Getenv("KS_CLOUD_API_URL"); cloudAPIURL != "" {
cloudURLs.CloudAPIURL = cloudAPIURL
}
if cloudAuthURL := os.Getenv("KS_CLOUD_AUTH_URL"); cloudAuthURL != "" {
cloudURLs.CloudAuthURL = cloudAuthURL
}
if cloudReportURL := os.Getenv("KS_CLOUD_REPORT_URL"); cloudReportURL != "" {
cloudURLs.CloudReportURL = cloudReportURL
}
if cloudUIURL := os.Getenv("KS_CLOUD_UI_URL"); cloudUIURL != "" {
cloudURLs.CloudUIURL = cloudUIURL
}
}
func updateCloudURLs(configObj *ConfigObj) {
cloudURLs := &CloudURLs{}
getCloudURLsFromEnv(cloudURLs)
if cloudURLs.CloudAPIURL != "" {
configObj.CloudAPIURL = cloudURLs.CloudAPIURL // override config CloudAPIURL
}
if cloudURLs.CloudAuthURL != "" {
configObj.CloudAuthURL = cloudURLs.CloudAuthURL // override config CloudAuthURL
}
if cloudURLs.CloudReportURL != "" {
configObj.CloudReportURL = cloudURLs.CloudReportURL // override config CloudReportURL
}
if cloudURLs.CloudUIURL != "" {
configObj.CloudUIURL = cloudURLs.CloudUIURL // override config CloudUIURL
}
}

View File

@@ -2,6 +2,7 @@ package cautils
import (
"encoding/json"
"os"
"testing"
"github.com/stretchr/testify/assert"
@@ -16,6 +17,10 @@ func mockConfigObj() *ConfigObj {
ClusterName: "ddd",
CustomerAdminEMail: "ab@cd",
Token: "eee",
CloudReportURL: "report.armo.cloud",
CloudAPIURL: "api.armosec.io",
CloudUIURL: "cloud.armosec.io",
CloudAuthURL: "auth.armosec.io",
}
}
func mockLocalConfig() *LocalConfig {
@@ -39,6 +44,10 @@ func TestConfig(t *testing.T) {
assert.Equal(t, co.AccountID, cop.AccountID)
assert.Equal(t, co.ClientID, cop.ClientID)
assert.Equal(t, co.SecretKey, cop.SecretKey)
assert.Equal(t, co.CloudReportURL, cop.CloudReportURL)
assert.Equal(t, co.CloudAPIURL, cop.CloudAPIURL)
assert.Equal(t, co.CloudUIURL, cop.CloudUIURL)
assert.Equal(t, co.CloudAuthURL, cop.CloudAuthURL)
assert.Equal(t, "", cop.ClusterName) // Not copied to bytes
assert.Equal(t, "", cop.CustomerAdminEMail) // Not copied to bytes
assert.Equal(t, "", cop.Token) // Not copied to bytes
@@ -60,6 +69,10 @@ func TestITenantConfig(t *testing.T) {
assert.Equal(t, co.ClusterName, lc.GetContextName())
assert.Equal(t, co.CustomerAdminEMail, lc.GetTenantEmail())
assert.Equal(t, co.Token, lc.GetToken())
assert.Equal(t, co.CloudReportURL, lc.GetCloudReportURL())
assert.Equal(t, co.CloudAPIURL, lc.GetCloudAPIURL())
assert.Equal(t, co.CloudUIURL, lc.GetCloudUIURL())
assert.Equal(t, co.CloudAuthURL, lc.GetCloudAuthURL())
// test ClusterConfig methods
assert.Equal(t, co.AccountID, c.GetAccountID())
@@ -68,6 +81,10 @@ func TestITenantConfig(t *testing.T) {
assert.Equal(t, co.ClusterName, c.GetContextName())
assert.Equal(t, co.CustomerAdminEMail, c.GetTenantEmail())
assert.Equal(t, co.Token, c.GetToken())
assert.Equal(t, co.CloudReportURL, c.GetCloudReportURL())
assert.Equal(t, co.CloudAPIURL, c.GetCloudAPIURL())
assert.Equal(t, co.CloudUIURL, c.GetCloudUIURL())
assert.Equal(t, co.CloudAuthURL, c.GetCloudAuthURL())
}
func TestUpdateConfigData(t *testing.T) {
@@ -80,6 +97,10 @@ func TestUpdateConfigData(t *testing.T) {
assert.Equal(t, c.GetAccountID(), configMap.Data["accountID"])
assert.Equal(t, c.GetClientID(), configMap.Data["clientID"])
assert.Equal(t, c.GetSecretKey(), configMap.Data["secretKey"])
assert.Equal(t, c.GetCloudReportURL(), configMap.Data["cloudReportURL"])
assert.Equal(t, c.GetCloudAPIURL(), configMap.Data["cloudAPIURL"])
assert.Equal(t, c.GetCloudUIURL(), configMap.Data["cloudUIURL"])
assert.Equal(t, c.GetCloudAuthURL(), configMap.Data["cloudAuthURL"])
}
func TestReadConfig(t *testing.T) {
@@ -97,6 +118,10 @@ func TestReadConfig(t *testing.T) {
assert.Equal(t, com.ClusterName, co.ClusterName)
assert.Equal(t, com.CustomerAdminEMail, co.CustomerAdminEMail)
assert.Equal(t, com.Token, co.Token)
assert.Equal(t, com.CloudReportURL, co.CloudReportURL)
assert.Equal(t, com.CloudAPIURL, co.CloudAPIURL)
assert.Equal(t, com.CloudUIURL, co.CloudUIURL)
assert.Equal(t, com.CloudAuthURL, co.CloudAuthURL)
}
func TestLoadConfigFromData(t *testing.T) {
@@ -120,6 +145,10 @@ func TestLoadConfigFromData(t *testing.T) {
assert.Equal(t, c.GetContextName(), co.ClusterName)
assert.Equal(t, c.GetTenantEmail(), co.CustomerAdminEMail)
assert.Equal(t, c.GetToken(), co.Token)
assert.Equal(t, c.GetCloudReportURL(), co.CloudReportURL)
assert.Equal(t, c.GetCloudAPIURL(), co.CloudAPIURL)
assert.Equal(t, c.GetCloudUIURL(), co.CloudUIURL)
assert.Equal(t, c.GetCloudAuthURL(), co.CloudAuthURL)
}
// use case: all data is in config.json
@@ -139,6 +168,10 @@ func TestLoadConfigFromData(t *testing.T) {
assert.Equal(t, c.GetAccountID(), co.AccountID)
assert.Equal(t, c.GetClientID(), co.ClientID)
assert.Equal(t, c.GetSecretKey(), co.SecretKey)
assert.Equal(t, c.GetCloudReportURL(), co.CloudReportURL)
assert.Equal(t, c.GetCloudAPIURL(), co.CloudAPIURL)
assert.Equal(t, c.GetCloudUIURL(), co.CloudUIURL)
assert.Equal(t, c.GetCloudAuthURL(), co.CloudAuthURL)
}
// use case: some data is in config.json
@@ -151,10 +184,12 @@ func TestLoadConfigFromData(t *testing.T) {
// add to map
configMap.Data["clientID"] = c.configObj.ClientID
configMap.Data["secretKey"] = c.configObj.SecretKey
configMap.Data["cloudReportURL"] = c.configObj.CloudReportURL
// delete the content
c.configObj.ClientID = ""
c.configObj.SecretKey = ""
c.configObj.CloudReportURL = ""
configMap.Data["config.json"] = string(c.GetConfigObj().Config())
loadConfigFromData(c.configObj, configMap.Data)
@@ -162,6 +197,7 @@ func TestLoadConfigFromData(t *testing.T) {
assert.NotEmpty(t, c.GetAccountID())
assert.NotEmpty(t, c.GetClientID())
assert.NotEmpty(t, c.GetSecretKey())
assert.NotEmpty(t, c.GetCloudReportURL())
}
// use case: some data is in config.json
@@ -222,3 +258,13 @@ func TestAdoptClusterName(t *testing.T) {
})
}
}
func TestUpdateCloudURLs(t *testing.T) {
co := mockConfigObj()
mockCloudAPIURL := "1-2-3-4.com"
os.Setenv("KS_CLOUD_API_URL", mockCloudAPIURL)
assert.NotEqual(t, co.CloudAPIURL, mockCloudAPIURL)
updateCloudURLs(co)
assert.Equal(t, co.CloudAPIURL, mockCloudAPIURL)
}

View File

@@ -15,7 +15,7 @@ import (
"github.com/kubescape/opa-utils/objectsenvelopes"
"github.com/kubescape/opa-utils/objectsenvelopes/localworkload"
"gopkg.in/yaml.v2"
"gopkg.in/yaml.v3"
)
var (
@@ -139,9 +139,9 @@ func loadFiles(rootPath string, filePaths []string) (map[string][]workloadinterf
for j := range w {
lw := localworkload.NewLocalWorkload(w[j].GetObject())
if relPath, err := filepath.Rel(rootPath, path); err == nil {
lw.SetPath(relPath)
lw.SetPath(fmt.Sprintf("%s:%d", relPath, j))
} else {
lw.SetPath(path)
lw.SetPath(fmt.Sprintf("%s:%d", path, j))
}
wSlice = append(wSlice, lw)
}

View File

@@ -1,8 +1,10 @@
package getter
import (
"fmt"
"strings"
"github.com/armosec/armoapi-go/armotypes"
"github.com/kubescape/opa-utils/gitregostore"
"github.com/kubescape/opa-utils/reporthandling"
"github.com/kubescape/opa-utils/reporthandling/attacktrack/v1alpha1"
@@ -54,13 +56,21 @@ func (drp *DownloadReleasedPolicy) ListFrameworks() ([]string, error) {
return drp.gs.GetOPAFrameworksNamesList()
}
func (drp *DownloadReleasedPolicy) ListControls(listType ListType) ([]string, error) {
switch listType {
case ListID:
return drp.gs.GetOPAControlsIDsList()
default:
return drp.gs.GetOPAControlsNamesList()
func (drp *DownloadReleasedPolicy) ListControls() ([]string, error) {
controlsIDsList, err := drp.gs.GetOPAControlsIDsList()
if err != nil {
return []string{}, err
}
controlsNamesList, err := drp.gs.GetOPAControlsNamesList()
if err != nil {
return []string{}, err
}
controlsNamesWithIDsList := make([]string, len(controlsIDsList))
// by design both slices have the same length
for i := range controlsIDsList {
controlsNamesWithIDsList[i] = fmt.Sprintf("%v|%v", controlsIDsList[i], controlsNamesList[i])
}
return controlsNamesWithIDsList, nil
}
func (drp *DownloadReleasedPolicy) GetControlsInputs(clusterName string) (map[string][]string, error) {
@@ -99,3 +109,11 @@ func contains(s []string, str string) bool {
}
return false
}
func (drp *DownloadReleasedPolicy) GetExceptions(clusterName string) ([]armotypes.PostureExceptionPolicy, error) {
exceptions, err := drp.gs.GetSystemPostureExceptionPolicies()
if err != nil {
return nil, err
}
return exceptions, nil
}

View File

@@ -0,0 +1,42 @@
package getter
import (
"context"
"os"
containeranalysis "cloud.google.com/go/containeranalysis/apiv1"
)
type GCPCloudAPI struct {
credentialsPath string
context context.Context
client *containeranalysis.Client
projectID string
credentialsCheck bool
}
func GetGlobalGCPCloudAPIConnector() *GCPCloudAPI {
if os.Getenv("KS_GCP_CREDENTIALS_PATH") == "" || os.Getenv("KS_GCP_PROJECT_ID") == "" {
return &GCPCloudAPI{
credentialsCheck: false,
}
} else {
return &GCPCloudAPI{
context: context.Background(),
credentialsPath: os.Getenv("KS_GCP_CREDENTIALS_PATH"),
projectID: os.Getenv("KS_GCP_PROJECT_ID"),
credentialsCheck: true,
}
}
}
func (api *GCPCloudAPI) SetClient(client *containeranalysis.Client) {
api.client = client
}
func (api *GCPCloudAPI) GetCredentialsPath() string { return api.credentialsPath }
func (api *GCPCloudAPI) GetClient() *containeranalysis.Client { return api.client }
func (api *GCPCloudAPI) GetProjectID() string { return api.projectID }
func (api *GCPCloudAPI) GetCredentialsCheck() bool { return api.credentialsCheck }
func (api *GCPCloudAPI) GetContext() context.Context { return api.context }

View File

@@ -6,19 +6,13 @@ import (
"github.com/kubescape/opa-utils/reporthandling/attacktrack/v1alpha1"
)
// supported listing
type ListType string
const ListID ListType = "id"
const ListName ListType = "name"
type IPolicyGetter interface {
GetFramework(name string) (*reporthandling.Framework, error)
GetFrameworks() ([]reporthandling.Framework, error)
GetControl(name string) (*reporthandling.Control, error)
ListFrameworks() ([]string, error)
ListControls(ListType) ([]string, error)
ListControls() ([]string, error)
}
type IExceptionsGetter interface {
@@ -28,10 +22,18 @@ type IBackend interface {
GetAccountID() string
GetClientID() string
GetSecretKey() string
GetCloudReportURL() string
GetCloudAPIURL() string
GetCloudUIURL() string
GetCloudAuthURL() string
SetAccountID(accountID string)
SetClientID(clientID string)
SetSecretKey(secretKey string)
SetCloudReportURL(cloudReportURL string)
SetCloudAPIURL(cloudAPIURL string)
SetCloudUIURL(cloudUIURL string)
SetCloudAuthURL(cloudAuthURL string)
GetTenant() (*TenantResponse, error)
}

View File

@@ -4,14 +4,12 @@ import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"strings"
"time"
"github.com/armosec/armoapi-go/armotypes"
logger "github.com/kubescape/go-logger"
"github.com/kubescape/go-logger/helpers"
"github.com/kubescape/opa-utils/reporthandling"
"github.com/kubescape/opa-utils/reporthandling/attacktrack/v1alpha1"
)
@@ -35,23 +33,22 @@ var (
// KSCloudAPI allows accessing the API of the Kubescape Cloud offering
type KSCloudAPI struct {
httpClient *http.Client
apiURL string
authURL string
erURL string
feURL string
accountID string
clientID string
secretKey string
authCookie string
feToken FeLoginResponse
loggedIn bool
httpClient *http.Client
cloudAPIURL string
cloudAuthURL string
cloudReportURL string
cloudUIURL string
accountID string
clientID string
secretKey string
authCookie string
feToken FeLoginResponse
loggedIn bool
}
var globalKSCloudAPIConnector *KSCloudAPI
func SetKSCloudAPIConnector(ksCloudAPI *KSCloudAPI) {
logger.L().Debug("Kubescape Cloud URLs", helpers.String("api", ksCloudAPI.apiURL), helpers.String("auth", ksCloudAPI.authURL), helpers.String("report", ksCloudAPI.erURL), helpers.String("UI", ksCloudAPI.feURL))
globalKSCloudAPIConnector = ksCloudAPI
}
@@ -65,10 +62,10 @@ func GetKSCloudAPIConnector() *KSCloudAPI {
func NewKSCloudAPIDev() *KSCloudAPI {
apiObj := newKSCloudAPI()
apiObj.apiURL = ksCloudDevBEURL
apiObj.authURL = ksCloudDevAUTHURL
apiObj.erURL = ksCloudDevERURL
apiObj.feURL = ksCloudDevFEURL
apiObj.cloudAPIURL = ksCloudDevBEURL
apiObj.cloudAuthURL = ksCloudDevAUTHURL
apiObj.cloudReportURL = ksCloudDevERURL
apiObj.cloudUIURL = ksCloudDevFEURL
return apiObj
}
@@ -76,10 +73,10 @@ func NewKSCloudAPIDev() *KSCloudAPI {
func NewKSCloudAPIProd() *KSCloudAPI {
apiObj := newKSCloudAPI()
apiObj.apiURL = ksCloudBEURL
apiObj.erURL = ksCloudERURL
apiObj.feURL = ksCloudFEURL
apiObj.authURL = ksCloudAUTHURL
apiObj.cloudAPIURL = ksCloudBEURL
apiObj.cloudReportURL = ksCloudERURL
apiObj.cloudUIURL = ksCloudFEURL
apiObj.cloudAuthURL = ksCloudAUTHURL
return apiObj
}
@@ -87,10 +84,10 @@ func NewKSCloudAPIProd() *KSCloudAPI {
func NewKSCloudAPIStaging() *KSCloudAPI {
apiObj := newKSCloudAPI()
apiObj.apiURL = ksCloudStageBEURL
apiObj.erURL = ksCloudStageERURL
apiObj.feURL = ksCloudStageFEURL
apiObj.authURL = ksCloudStageAUTHURL
apiObj.cloudAPIURL = ksCloudStageBEURL
apiObj.cloudReportURL = ksCloudStageERURL
apiObj.cloudUIURL = ksCloudStageFEURL
apiObj.cloudAuthURL = ksCloudStageAUTHURL
return apiObj
}
@@ -98,10 +95,10 @@ func NewKSCloudAPIStaging() *KSCloudAPI {
func NewKSCloudAPICustomized(ksCloudERURL, ksCloudBEURL, ksCloudFEURL, ksCloudAUTHURL string) *KSCloudAPI {
apiObj := newKSCloudAPI()
apiObj.erURL = ksCloudERURL
apiObj.apiURL = ksCloudBEURL
apiObj.feURL = ksCloudFEURL
apiObj.authURL = ksCloudAUTHURL
apiObj.cloudReportURL = ksCloudERURL
apiObj.cloudAPIURL = ksCloudBEURL
apiObj.cloudUIURL = ksCloudFEURL
apiObj.cloudAuthURL = ksCloudAUTHURL
return apiObj
}
@@ -136,17 +133,22 @@ func (api *KSCloudAPI) Get(fullURL string, headers map[string]string) (string, e
return HttpGetter(api.httpClient, fullURL, headers)
}
func (api *KSCloudAPI) GetAccountID() string { return api.accountID }
func (api *KSCloudAPI) IsLoggedIn() bool { return api.loggedIn }
func (api *KSCloudAPI) GetClientID() string { return api.clientID }
func (api *KSCloudAPI) GetSecretKey() string { return api.secretKey }
func (api *KSCloudAPI) GetFrontendURL() string { return api.feURL }
func (api *KSCloudAPI) GetApiURL() string { return api.apiURL }
func (api *KSCloudAPI) GetAuthURL() string { return api.authURL }
func (api *KSCloudAPI) GetReportReceiverURL() string { return api.erURL }
func (api *KSCloudAPI) SetAccountID(accountID string) { api.accountID = accountID }
func (api *KSCloudAPI) SetClientID(clientID string) { api.clientID = clientID }
func (api *KSCloudAPI) SetSecretKey(secretKey string) { api.secretKey = secretKey }
func (api *KSCloudAPI) GetAccountID() string { return api.accountID }
func (api *KSCloudAPI) IsLoggedIn() bool { return api.loggedIn }
func (api *KSCloudAPI) GetClientID() string { return api.clientID }
func (api *KSCloudAPI) GetSecretKey() string { return api.secretKey }
func (api *KSCloudAPI) GetCloudReportURL() string { return api.cloudReportURL }
func (api *KSCloudAPI) GetCloudAPIURL() string { return api.cloudAPIURL }
func (api *KSCloudAPI) GetCloudUIURL() string { return api.cloudUIURL }
func (api *KSCloudAPI) GetCloudAuthURL() string { return api.cloudAuthURL }
func (api *KSCloudAPI) SetAccountID(accountID string) { api.accountID = accountID }
func (api *KSCloudAPI) SetClientID(clientID string) { api.clientID = clientID }
func (api *KSCloudAPI) SetSecretKey(secretKey string) { api.secretKey = secretKey }
func (api *KSCloudAPI) SetCloudReportURL(cloudReportURL string) { api.cloudReportURL = cloudReportURL }
func (api *KSCloudAPI) SetCloudAPIURL(cloudAPIURL string) { api.cloudAPIURL = cloudAPIURL }
func (api *KSCloudAPI) SetCloudUIURL(cloudUIURL string) { api.cloudUIURL = cloudUIURL }
func (api *KSCloudAPI) SetCloudAuthURL(cloudAuthURL string) { api.cloudAuthURL = cloudAuthURL }
func (api *KSCloudAPI) GetAttackTracks() ([]v1alpha1.AttackTrack, error) {
respStr, err := api.Get(api.getAttackTracksURL(), nil)
@@ -304,7 +306,7 @@ func (api *KSCloudAPI) ListFrameworks() ([]string, error) {
return frameworkList, nil
}
func (api *KSCloudAPI) ListControls(l ListType) ([]string, error) {
func (api *KSCloudAPI) ListControls() ([]string, error) {
return nil, fmt.Errorf("control api is not public")
}
@@ -356,7 +358,7 @@ func (api *KSCloudAPI) Login() error {
return fmt.Errorf("error authenticating: %d", resp.StatusCode)
}
responseBody, err := ioutil.ReadAll(resp.Body)
responseBody, err := io.ReadAll(resp.Body)
if err != nil {
return err
}

View File

@@ -13,7 +13,7 @@ var NativeFrameworks = []string{"nsa", "mitre", "armobest", "devopsbest"}
func (api *KSCloudAPI) getFrameworkURL(frameworkName string) string {
u := url.URL{}
u.Scheme, u.Host = parseHost(api.GetApiURL())
u.Scheme, u.Host = parseHost(api.GetCloudAPIURL())
u.Path = "api/v1/armoFrameworks"
q := u.Query()
q.Add("customerGUID", api.getCustomerGUIDFallBack())
@@ -30,7 +30,7 @@ func (api *KSCloudAPI) getFrameworkURL(frameworkName string) string {
func (api *KSCloudAPI) getAttackTracksURL() string {
u := url.URL{}
u.Scheme, u.Host = parseHost(api.GetApiURL())
u.Scheme, u.Host = parseHost(api.GetCloudAPIURL())
u.Path = "api/v1/attackTracks"
q := u.Query()
q.Add("customerGUID", api.getCustomerGUIDFallBack())
@@ -41,7 +41,7 @@ func (api *KSCloudAPI) getAttackTracksURL() string {
func (api *KSCloudAPI) getListFrameworkURL() string {
u := url.URL{}
u.Scheme, u.Host = parseHost(api.GetApiURL())
u.Scheme, u.Host = parseHost(api.GetCloudAPIURL())
u.Path = "api/v1/armoFrameworks"
q := u.Query()
q.Add("customerGUID", api.getCustomerGUIDFallBack())
@@ -51,7 +51,7 @@ func (api *KSCloudAPI) getListFrameworkURL() string {
}
func (api *KSCloudAPI) getExceptionsURL(clusterName string) string {
u := url.URL{}
u.Scheme, u.Host = parseHost(api.GetApiURL())
u.Scheme, u.Host = parseHost(api.GetCloudAPIURL())
u.Path = "api/v1/armoPostureExceptions"
q := u.Query()
@@ -66,7 +66,7 @@ func (api *KSCloudAPI) getExceptionsURL(clusterName string) string {
func (api *KSCloudAPI) exceptionsURL(exceptionsPolicyName string) string {
u := url.URL{}
u.Scheme, u.Host = parseHost(api.GetApiURL())
u.Scheme, u.Host = parseHost(api.GetCloudAPIURL())
u.Path = "api/v1/postureExceptionPolicy"
q := u.Query()
@@ -88,7 +88,7 @@ func (api *KSCloudAPI) getAccountConfigDefault(clusterName string) string {
func (api *KSCloudAPI) getAccountConfig(clusterName string) string {
u := url.URL{}
u.Scheme, u.Host = parseHost(api.GetApiURL())
u.Scheme, u.Host = parseHost(api.GetCloudAPIURL())
u.Path = "api/v1/armoCustomerConfiguration"
q := u.Query()
@@ -103,21 +103,21 @@ func (api *KSCloudAPI) getAccountConfig(clusterName string) string {
func (api *KSCloudAPI) getAccountURL() string {
u := url.URL{}
u.Scheme, u.Host = parseHost(api.GetApiURL())
u.Scheme, u.Host = parseHost(api.GetCloudAPIURL())
u.Path = "api/v1/createTenant"
return u.String()
}
func (api *KSCloudAPI) getApiToken() string {
u := url.URL{}
u.Scheme, u.Host = parseHost(api.GetAuthURL())
u.Scheme, u.Host = parseHost(api.GetCloudAuthURL())
u.Path = "identity/resources/auth/v1/api-token"
return u.String()
}
func (api *KSCloudAPI) getOpenidCustomers() string {
u := url.URL{}
u.Scheme, u.Host = parseHost(api.GetApiURL())
u.Scheme, u.Host = parseHost(api.GetCloudAPIURL())
u.Path = "api/v1/openid_customers"
return u.String()
}

View File

@@ -65,16 +65,16 @@ func (lp *LoadPolicy) GetControl(controlName string) (*reporthandling.Control, e
}
func (lp *LoadPolicy) GetFramework(frameworkName string) (*reporthandling.Framework, error) {
framework := &reporthandling.Framework{}
var framework reporthandling.Framework
var err error
for _, filePath := range lp.filePaths {
framework = reporthandling.Framework{}
f, err := os.ReadFile(filePath)
if err != nil {
return nil, err
}
if err = json.Unmarshal(f, framework); err != nil {
return framework, err
if err = json.Unmarshal(f, &framework); err != nil {
return nil, err
}
if strings.EqualFold(frameworkName, framework.Name) {
break
@@ -84,7 +84,7 @@ func (lp *LoadPolicy) GetFramework(frameworkName string) (*reporthandling.Framew
return nil, fmt.Errorf("framework from file not matching")
}
return framework, err
return &framework, err
}
func (lp *LoadPolicy) GetFrameworks() ([]reporthandling.Framework, error) {
@@ -109,7 +109,7 @@ func (lp *LoadPolicy) ListFrameworks() ([]string, error) {
return fwNames, nil
}
func (lp *LoadPolicy) ListControls(listType ListType) ([]string, error) {
func (lp *LoadPolicy) ListControls() ([]string, error) {
// TODO - Support
return []string{}, fmt.Errorf("loading controls list from file is not supported")
}
@@ -130,14 +130,19 @@ func (lp *LoadPolicy) GetControlsInputs(clusterName string) (map[string][]string
filePath := lp.filePath()
accountConfig := &armotypes.CustomerConfig{}
f, err := os.ReadFile(filePath)
fileName := filepath.Base(filePath)
if err != nil {
return nil, err
formattedError := fmt.Errorf("Error opening %s file, \"controls-config\" will be downloaded from ARMO management portal", fileName)
return nil, formattedError
}
if err = json.Unmarshal(f, &accountConfig.Settings.PostureControlInputs); err == nil {
return accountConfig.Settings.PostureControlInputs, nil
}
return nil, err
formattedError := fmt.Errorf("Error reading %s file, %s, \"controls-config\" will be downloaded from ARMO management portal", fileName, err.Error())
return nil, formattedError
}
// temporary support for a list of files

View File

@@ -3,7 +3,6 @@ package cautils
import (
_ "embed"
"encoding/json"
"io/ioutil"
"os"
"path/filepath"
"strings"
@@ -39,7 +38,7 @@ func (s *HelmChartTestSuite) SetupSuite() {
}
var obj interface{}
file, _ := ioutil.ReadFile(filepath.Join("testdata", "helm_expected_default_values.json"))
file, _ := os.ReadFile(filepath.Join("testdata", "helm_expected_default_values.json"))
_ = json.Unmarshal([]byte(file), &obj)
s.expectedDefaultValues = obj.(map[string]interface{})
}

View File

@@ -15,7 +15,12 @@ type RootInfo struct {
KSCloudBEURLs string // Kubescape Cloud URL
KSCloudBEURLsDep string // Kubescape Cloud URL
}
type CloudURLs struct {
CloudReportURL string
CloudAPIURL string
CloudUIURL string
CloudAuthURL string
}
type Credentials struct {

View File

@@ -3,7 +3,6 @@ package cautils
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"
@@ -159,7 +158,7 @@ func (scanInfo *ScanInfo) setUseArtifactsFrom() {
scanInfo.UseArtifactsFrom = dir
}
// set frameworks files
files, err := ioutil.ReadDir(scanInfo.UseArtifactsFrom)
files, err := os.ReadDir(scanInfo.UseArtifactsFrom)
if err != nil {
logger.L().Fatal("failed to read files from directory", helpers.String("dir", scanInfo.UseArtifactsFrom), helpers.Error(err))
}
@@ -419,6 +418,7 @@ func metadataGitLocal(input string) (*reporthandlingv2.RepoContextMetadata, erro
Date: commit.Committer.Date,
CommitterName: commit.Committer.Name,
}
context.LocalRootPath = getAbsPath(input)
return context, nil
}

View File

@@ -18,7 +18,8 @@ func TestSetContextMetadata(t *testing.T) {
assert.Nil(t, ctx.HelmContextMetadata)
assert.Nil(t, ctx.RepoContextMetadata)
}
{
// TODO: tests were commented out due to actual http calls ; http calls should be mocked.
/*{
ctx := reporthandlingv2.ContextMetadata{}
setContextMetadata(&ctx, "https://github.com/kubescape/kubescape")
@@ -31,7 +32,7 @@ func TestSetContextMetadata(t *testing.T) {
assert.Equal(t, "kubescape", ctx.RepoContextMetadata.Repo)
assert.Equal(t, "kubescape", ctx.RepoContextMetadata.Owner)
assert.Equal(t, "master", ctx.RepoContextMetadata.Branch)
}
}*/
}
func TestGetHostname(t *testing.T) {

View File

@@ -19,6 +19,7 @@ const SKIP_VERSION_CHECK = "KS_SKIP_UPDATE_CHECK"
var BuildNumber string
var Client string
var LatestReleaseVersion string
const UnknownBuildNumber = "unknown"
@@ -108,9 +109,11 @@ func (v *VersionCheckHandler) CheckLatestVersion(versionData *VersionCheckReques
return fmt.Errorf("failed to get latest version")
}
LatestReleaseVersion := latestVersion.ClientUpdate
if latestVersion.ClientUpdate != "" {
if BuildNumber != "" && semver.Compare(BuildNumber, latestVersion.ClientUpdate) == -1 {
logger.L().Warning(warningMessage(latestVersion.ClientUpdate))
if BuildNumber != "" && semver.Compare(BuildNumber, LatestReleaseVersion) == -1 {
logger.L().Warning(warningMessage(LatestReleaseVersion))
}
}

View File

@@ -3,6 +3,7 @@ package cautils
import (
"strings"
"github.com/kubescape/k8s-interface/cloudsupport"
"github.com/kubescape/opa-utils/reporthandling/apis"
)
@@ -17,8 +18,12 @@ var (
"LinuxKernelVariables",
"KubeletInfo",
"KubeProxyInfo",
"ControlPlaneInfo",
}
CloudResources = []string{
"ClusterDescribe",
string(cloudsupport.TypeApiServerInfo),
}
CloudResources = []string{"ClusterDescribe"}
)
func MapKSResource(ksResourceMap *KSResources, resources []string) []string {

View File

@@ -19,6 +19,18 @@ func (ks *Kubescape) SetCachedConfig(setConfig *metav1.SetConfig) error {
if setConfig.ClientID != "" {
tenant.GetConfigObj().ClientID = setConfig.ClientID
}
if setConfig.CloudAPIURL != "" {
tenant.GetConfigObj().CloudAPIURL = setConfig.CloudAPIURL
}
if setConfig.CloudAuthURL != "" {
tenant.GetConfigObj().CloudAuthURL = setConfig.CloudAuthURL
}
if setConfig.CloudReportURL != "" {
tenant.GetConfigObj().CloudReportURL = setConfig.CloudReportURL
}
if setConfig.CloudUIURL != "" {
tenant.GetConfigObj().CloudUIURL = setConfig.CloudUIURL
}
return tenant.UpdateCachedConfig()
}

View File

@@ -106,7 +106,7 @@ func downloadExceptions(downloadInfo *metav1.DownloadInfo) error {
var err error
tenant := getTenantConfig(&downloadInfo.Credentials, "", "", getKubernetesApi())
exceptionsGetter := getExceptionsGetter("")
exceptionsGetter := getExceptionsGetter("", tenant.GetAccountID(), nil)
exceptions := []armotypes.PostureExceptionPolicy{}
if tenant.GetAccountID() != "" {
exceptions, err = exceptionsGetter.GetExceptions(tenant.GetContextName())

View File

@@ -32,13 +32,24 @@ func getTenantConfig(credentials *cautils.Credentials, clusterName string, custo
return cautils.NewClusterConfig(k8s, getter.GetKSCloudAPIConnector(), credentials, clusterName, customClusterName)
}
func getExceptionsGetter(useExceptions string) getter.IExceptionsGetter {
func getExceptionsGetter(useExceptions string, accountID string, downloadReleasedPolicy *getter.DownloadReleasedPolicy) getter.IExceptionsGetter {
if useExceptions != "" {
// load exceptions from file
return getter.NewLoadPolicy([]string{useExceptions})
} else {
}
if accountID != "" {
// download exceptions from Kubescape Cloud backend
return getter.GetKSCloudAPIConnector()
}
// download exceptions from GitHub
if downloadReleasedPolicy == nil {
downloadReleasedPolicy = getter.NewDownloadReleasedPolicy()
}
if err := downloadReleasedPolicy.SetRegoObjects(); err != nil {
logger.L().Warning("failed to get exceptions from github release, this may affect the scanning results", helpers.Error(err))
}
return downloadReleasedPolicy
}
func getRBACHandler(tenantConfig cautils.ITenantConfig, k8s *k8sinterface.KubernetesApi, submit bool) *cautils.RBACObjects {
@@ -58,7 +69,7 @@ func getReporter(tenantConfig cautils.ITenantConfig, reportID string, submit, fw
}
if tenantConfig.GetAccountID() == "" {
// Add link only when scanning a cluster using a framework
return reporterv2.NewReportMock(reporterv2.NO_SUBMIT_QUERY, "run kubescape with the '--submit' flag")
return reporterv2.NewReportMock("https://hub.armosec.io/docs/installing-kubescape", "run kubescape with the '--account' flag")
}
var message string
if !fwScan {
@@ -128,16 +139,21 @@ func policyIdentifierNames(pi []cautils.PolicyIdentifier) string {
func setSubmitBehavior(scanInfo *cautils.ScanInfo, tenantConfig cautils.ITenantConfig) {
/*
If "First run (local config not found)" -
Default/keep-local - Do not send report
Submit - Create tenant & Submit report
If CloudReportURL not set - Do not send report
If "Submitted" -
If There is no account - Do not send report
If There is account -
keep-local - Do not send report
Default/Submit - Submit report
Default - Submit report
*/
if getter.GetKSCloudAPIConnector().GetCloudAPIURL() == "" {
scanInfo.Submit = false
return
}
// do not submit control scanning
if !scanInfo.FrameworkScan {
scanInfo.Submit = false
@@ -150,27 +166,26 @@ func setSubmitBehavior(scanInfo *cautils.ScanInfo, tenantConfig cautils.ITenantC
return
}
if tenantConfig.IsConfigFound() { // config found in cache (submitted)
if !scanInfo.Local {
if tenantConfig.GetAccountID() != "" {
if _, err := uuid.Parse(tenantConfig.GetAccountID()); err != nil {
scanInfo.Submit = false
return
}
}
// Submit report
scanInfo.Submit = true
}
if scanInfo.Local {
scanInfo.Submit = false
return
}
// If There is no account, or if the account is not legal, do not submit
if _, err := uuid.Parse(tenantConfig.GetAccountID()); err != nil {
scanInfo.Submit = false
} else {
scanInfo.Submit = true
}
}
// setPolicyGetter set the policy getter - local file/github release/Kubescape Cloud API
func getPolicyGetter(loadPoliciesFromFile []string, tennatEmail string, frameworkScope bool, downloadReleasedPolicy *getter.DownloadReleasedPolicy) getter.IPolicyGetter {
func getPolicyGetter(loadPoliciesFromFile []string, tenantEmail string, frameworkScope bool, downloadReleasedPolicy *getter.DownloadReleasedPolicy) getter.IPolicyGetter {
if len(loadPoliciesFromFile) > 0 {
return getter.NewLoadPolicy(loadPoliciesFromFile)
}
if tennatEmail != "" && frameworkScope {
if tenantEmail != "" && getter.GetKSCloudAPIConnector().GetCloudAPIURL() != "" && frameworkScope {
g := getter.GetKSCloudAPIConnector() // download policy from Kubescape Cloud backend
return g
}

View File

@@ -6,8 +6,11 @@ import (
"sort"
"strings"
"github.com/kubescape/kubescape/v2/core/cautils/getter"
"github.com/kubescape/kubescape/v2/core/cautils"
metav1 "github.com/kubescape/kubescape/v2/core/meta/datastructures/v1"
"github.com/kubescape/kubescape/v2/core/pkg/resultshandling/printer"
v2 "github.com/kubescape/kubescape/v2/core/pkg/resultshandling/printer/v2"
"github.com/olekukonko/tablewriter"
)
var listFunc = map[string]func(*metav1.ListPolicies) ([]string, error){
@@ -16,7 +19,7 @@ var listFunc = map[string]func(*metav1.ListPolicies) ([]string, error){
"exceptions": listExceptions,
}
var listFormatFunc = map[string]func(*metav1.ListPolicies, []string){
var listFormatFunc = map[string]func(string, []string){
"pretty-print": prettyPrintListFormat,
"json": jsonListFormat,
}
@@ -29,14 +32,18 @@ func ListSupportActions() []string {
return commands
}
func (ks *Kubescape) List(listPolicies *metav1.ListPolicies) error {
if f, ok := listFunc[listPolicies.Target]; ok {
policies, err := f(listPolicies)
if policyListerFunc, ok := listFunc[listPolicies.Target]; ok {
policies, err := policyListerFunc(listPolicies)
if err != nil {
return err
}
sort.Strings(policies)
listFormatFunc[listPolicies.Format](listPolicies, policies)
if listFormatFunction, ok := listFormatFunc[listPolicies.Format]; ok {
listFormatFunction(listPolicies.Target, policies)
} else {
return fmt.Errorf("Invalid format \"%s\", Supported formats: 'pretty-print'/'json' ", listPolicies.Format)
}
return nil
}
@@ -45,28 +52,24 @@ func (ks *Kubescape) List(listPolicies *metav1.ListPolicies) error {
func listFrameworks(listPolicies *metav1.ListPolicies) ([]string, error) {
tenant := getTenantConfig(&listPolicies.Credentials, "", "", getKubernetesApi()) // change k8sinterface
g := getPolicyGetter(nil, tenant.GetTenantEmail(), true, nil)
policyGetter := getPolicyGetter(nil, tenant.GetTenantEmail(), true, nil)
return listFrameworksNames(g), nil
return listFrameworksNames(policyGetter), nil
}
func listControls(listPolicies *metav1.ListPolicies) ([]string, error) {
tenant := getTenantConfig(&listPolicies.Credentials, "", "", getKubernetesApi()) // change k8sinterface
g := getPolicyGetter(nil, tenant.GetTenantEmail(), false, nil)
l := getter.ListName
if listPolicies.ListIDs {
l = getter.ListID
}
return g.ListControls(l)
policyGetter := getPolicyGetter(nil, tenant.GetTenantEmail(), false, nil)
return policyGetter.ListControls()
}
func listExceptions(listPolicies *metav1.ListPolicies) ([]string, error) {
// load tenant metav1
getTenantConfig(&listPolicies.Credentials, "", "", getKubernetesApi())
tenant := getTenantConfig(&listPolicies.Credentials, "", "", getKubernetesApi())
var exceptionsNames []string
ksCloudAPI := getExceptionsGetter("")
ksCloudAPI := getExceptionsGetter("", tenant.GetAccountID(), nil)
exceptions, err := ksCloudAPI.GetExceptions("")
if err != nil {
return exceptionsNames, err
@@ -77,12 +80,73 @@ func listExceptions(listPolicies *metav1.ListPolicies) ([]string, error) {
return exceptionsNames, nil
}
func prettyPrintListFormat(listPolicies *metav1.ListPolicies, policies []string) {
sep := "\n * "
fmt.Printf("Supported %s:%s%s\n", listPolicies.Target, sep, strings.Join(policies, sep))
func prettyPrintListFormat(targetPolicy string, policies []string) {
if targetPolicy == "controls" {
prettyPrintControls(policies)
return
}
header := fmt.Sprintf("Supported %s", targetPolicy)
policyTable := tablewriter.NewWriter(printer.GetWriter(""))
policyTable.SetAutoWrapText(true)
policyTable.SetHeader([]string{header})
policyTable.SetHeaderLine(true)
policyTable.SetRowLine(true)
data := v2.Matrix{}
controlRows := generatePolicyRows(policies)
data = append(data, controlRows...)
policyTable.SetAlignment(tablewriter.ALIGN_CENTER)
policyTable.AppendBulk(data)
policyTable.Render()
}
func jsonListFormat(listPolicies *metav1.ListPolicies, policies []string) {
func jsonListFormat(targetPolicy string, policies []string) {
j, _ := json.MarshalIndent(policies, "", " ")
fmt.Printf("%s\n", j)
}
func prettyPrintControls(policies []string) {
controlsTable := tablewriter.NewWriter(printer.GetWriter(""))
controlsTable.SetAutoWrapText(true)
controlsTable.SetHeader([]string{"Control ID", "Control Name", "Docs"})
controlsTable.SetHeaderLine(true)
controlsTable.SetRowLine(true)
data := v2.Matrix{}
controlRows := generateControlRows(policies)
data = append(data, controlRows...)
controlsTable.AppendBulk(data)
controlsTable.Render()
}
func generateControlRows(policies []string) [][]string {
rows := [][]string{}
for _, control := range policies {
idAndControl := strings.Split(control, "|")
id, control := idAndControl[0], idAndControl[1]
docs := cautils.GetControlLink(id)
currentRow := []string{id, control, docs}
rows = append(rows, currentRow)
}
return rows
}
func generatePolicyRows(policies []string) [][]string {
rows := [][]string{}
for _, policy := range policies {
currentRow := []string{policy}
rows = append(rows, currentRow)
}
return rows
}

View File

@@ -122,7 +122,7 @@ func (ks *Kubescape) Scan(scanInfo *cautils.ScanInfo) (*resultshandling.ResultsH
// set policy getter only after setting the customerGUID
scanInfo.Getters.PolicyGetter = getPolicyGetter(scanInfo.UseFrom, interfaces.tenantConfig.GetTenantEmail(), scanInfo.FrameworkScan, downloadReleasedPolicy)
scanInfo.Getters.ControlsInputsGetter = getConfigInputsGetter(scanInfo.ControlsInputs, interfaces.tenantConfig.GetAccountID(), downloadReleasedPolicy)
scanInfo.Getters.ExceptionsGetter = getExceptionsGetter(scanInfo.UseExceptions)
scanInfo.Getters.ExceptionsGetter = getExceptionsGetter(scanInfo.UseExceptions, interfaces.tenantConfig.GetAccountID(), downloadReleasedPolicy)
scanInfo.Getters.AttackTracksGetter = getAttackTracksGetter(interfaces.tenantConfig.GetAccountID(), downloadReleasedPolicy)
// TODO - list supported frameworks/controls

View File

@@ -3,9 +3,13 @@ package v1
import "io"
type SetConfig struct {
Account string
ClientID string
SecretKey string
Account string
ClientID string
SecretKey string
CloudReportURL string
CloudAPIURL string
CloudUIURL string
CloudAuthURL string
}
type ViewConfig struct {

View File

@@ -4,7 +4,6 @@ import "github.com/kubescape/kubescape/v2/core/cautils"
type ListPolicies struct {
Target string
ListIDs bool
Format string
Credentials cautils.Credentials
}

View File

@@ -8,7 +8,7 @@ import (
"github.com/kubescape/opa-utils/reporthandling"
)
var mockControl_0006 = `{"guid":"","name":"Allowed hostPath","attributes":{"armoBuiltin":true},"id":"C-0006","controlID":"C-0006","creationTime":"","description":"Mounting host directory to the container can be abused to get access to sensitive data and gain persistence on the host machine.","remediation":"Refrain from using host path mount.","rules":[{"guid":"","name":"alert-rw-hostpath","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Persistence::Writable hostPath mount, Lateral Movement::Writable volume mounts on the host"},"creationTime":"","rule":"package armo_builtins\n\n# input: pod\n# apiversion: v1\n# does: returns hostPath volumes\n\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n volumes := pod.spec.volumes\n volume := volumes[_]\n volume.hostPath\n\tcontainer := pod.spec.containers[i]\n\tvolumeMount := container.volumeMounts[k]\n\tvolumeMount.name == volume.name\n\tbegginingOfPath := \"spec.\"\n\tresult := isRWMount(volumeMount, begginingOfPath, i, k)\n\n podname := pod.metadata.name\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"pod: %v has: %v as hostPath volume\", [podname, volume.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"failedPaths\": [result],\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n#handles majority of workload resources\ndeny[msga] {\n\twl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n volumes := wl.spec.template.spec.volumes\n volume := volumes[_]\n volume.hostPath\n\tcontainer := wl.spec.template.spec.containers[i]\n\tvolumeMount := container.volumeMounts[k]\n\tvolumeMount.name == volume.name\n\tbegginingOfPath := \"spec.template.spec.\"\n\tresult := isRWMount(volumeMount, begginingOfPath, i, k)\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"%v: %v has: %v as hostPath volume\", [wl.kind, wl.metadata.name, volume.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"failedPaths\": [result],\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t\n\t}\n}\n\n#handles CronJobs\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n volumes := wl.spec.jobTemplate.spec.template.spec.volumes\n volume := volumes[_]\n volume.hostPath\n\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[i]\n\tvolumeMount := container.volumeMounts[k]\n\tvolumeMount.name == volume.name\n\tbegginingOfPath := \"spec.jobTemplate.spec.template.spec.\"\n\tresult := isRWMount(volumeMount, begginingOfPath, i, k)\n\n\tmsga := {\n\t\"alertMessage\": sprintf(\"%v: %v has: %v as hostPath volume\", [wl.kind, wl.metadata.name, volume.name]),\n\t\"packagename\": \"armo_builtins\",\n\t\"alertScore\": 7,\n\t\"failedPaths\": [result],\n\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\nisRWMount(mount, begginingOfPath, i, k) = path {\n not mount.readOnly == true\n not mount.readOnly == false\n path = \"\"\n}\nisRWMount(mount, begginingOfPath, i, k) = path {\n mount.readOnly == false\n path = sprintf(\"%vcontainers[%v].volumeMounts[%v].readOnly\", [begginingOfPath, format_int(i, 10), format_int(k, 10)])\n} ","resourceEnumerator":"","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","CronJob","Pod"]}],"ruleDependencies":[{"packageName":"cautils"},{"packageName":"kubernetes.api.client"}],"configInputs":null,"controlConfigInputs":null,"description":"determines if any workload contains a hostPath volume with rw permissions","remediation":"Set the readOnly field of the mount to true","ruleQuery":""}],"rulesIDs":[""],"baseScore":6}`
var mockControl_0006 = `{"guid":"","name":"HostPath mount","attributes":{"armoBuiltin":true},"id":"C-0048","controlID":"C-0048","creationTime":"","description":"Mounting host directory to the container can be abused to get access to sensitive data and gain persistence on the host machine.","remediation":"Refrain from using host path mount.","rules":[{"guid":"","name":"alert-rw-hostpath","attributes":{"armoBuiltin":true,"m$K8sThreatMatrix":"Persistence::Writable hostPath mount, Lateral Movement::Writable volume mounts on the host"},"creationTime":"","rule":"package armo_builtins\n\n# input: pod\n# apiversion: v1\n# does: returns hostPath volumes\n\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n volumes := pod.spec.volumes\n volume := volumes[_]\n volume.hostPath\n\tcontainer := pod.spec.containers[i]\n\tvolumeMount := container.volumeMounts[k]\n\tvolumeMount.name == volume.name\n\tbegginingOfPath := \"spec.\"\n\tresult := isRWMount(volumeMount, begginingOfPath, i, k)\n\n podname := pod.metadata.name\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"pod: %v has: %v as hostPath volume\", [podname, volume.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"failedPaths\": [result],\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n#handles majority of workload resources\ndeny[msga] {\n\twl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n volumes := wl.spec.template.spec.volumes\n volume := volumes[_]\n volume.hostPath\n\tcontainer := wl.spec.template.spec.containers[i]\n\tvolumeMount := container.volumeMounts[k]\n\tvolumeMount.name == volume.name\n\tbegginingOfPath := \"spec.template.spec.\"\n\tresult := isRWMount(volumeMount, begginingOfPath, i, k)\n\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"%v: %v has: %v as hostPath volume\", [wl.kind, wl.metadata.name, volume.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"failedPaths\": [result],\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t\n\t}\n}\n\n#handles CronJobs\ndeny[msga] {\n\twl := input[_]\n\twl.kind == \"CronJob\"\n volumes := wl.spec.jobTemplate.spec.template.spec.volumes\n volume := volumes[_]\n volume.hostPath\n\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[i]\n\tvolumeMount := container.volumeMounts[k]\n\tvolumeMount.name == volume.name\n\tbegginingOfPath := \"spec.jobTemplate.spec.template.spec.\"\n\tresult := isRWMount(volumeMount, begginingOfPath, i, k)\n\n\tmsga := {\n\t\"alertMessage\": sprintf(\"%v: %v has: %v as hostPath volume\", [wl.kind, wl.metadata.name, volume.name]),\n\t\"packagename\": \"armo_builtins\",\n\t\"alertScore\": 7,\n\t\"failedPaths\": [result],\n\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\nisRWMount(mount, begginingOfPath, i, k) = path {\n not mount.readOnly == true\n not mount.readOnly == false\n path = \"\"\n}\nisRWMount(mount, begginingOfPath, i, k) = path {\n mount.readOnly == false\n path = sprintf(\"%vcontainers[%v].volumeMounts[%v].readOnly\", [begginingOfPath, format_int(i, 10), format_int(k, 10)])\n} ","resourceEnumerator":"","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","CronJob","Pod"]}],"ruleDependencies":[{"packageName":"cautils"},{"packageName":"kubernetes.api.client"}],"configInputs":null,"controlConfigInputs":null,"description":"determines if any workload contains a hostPath volume with rw permissions","remediation":"Set the readOnly field of the mount to true","ruleQuery":""}],"rulesIDs":[""],"baseScore":6}`
var mockControl_0044 = `{"guid":"","name":"Container hostPort","attributes":{"armoBuiltin":true},"id":"C-0044","controlID":"C-0044","creationTime":"","description":"Configuring hostPort limits you to a particular port, and if any two workloads that specify the same HostPort they cannot be deployed to the same node. Therefore, if the number of replica of such workload is higher than the number of nodes, the deployment will fail.","remediation":"Avoid usage of hostPort unless it is absolutely necessary. Use NodePort / ClusterIP instead.","rules":[{"guid":"","name":"container-hostPort","attributes":{"armoBuiltin":true},"creationTime":"","rule":"package armo_builtins\n\n\n# Fails if pod has container with hostPort\ndeny[msga] {\n pod := input[_]\n pod.kind == \"Pod\"\n container := pod.spec.containers[i]\n\tbegginingOfPath := \"spec.\"\n\tpath := isHostPort(container, i, begginingOfPath)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Container: %v has Host-port\", [ container.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"failedPaths\": path,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [pod]\n\t\t}\n\t}\n}\n\n# Fails if workload has container with hostPort\ndeny[msga] {\n wl := input[_]\n\tspec_template_spec_patterns := {\"Deployment\",\"ReplicaSet\",\"DaemonSet\",\"StatefulSet\",\"Job\"}\n\tspec_template_spec_patterns[wl.kind]\n container := wl.spec.template.spec.containers[i]\n\tbegginingOfPath := \"spec.template.spec.\"\n path := isHostPort(container, i, begginingOfPath)\n\tmsga := {\n\t\t\"alertMessage\": sprintf(\"Container: %v in %v: %v has Host-port\", [ container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"failedPaths\": path,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n# Fails if cronjob has container with hostPort\ndeny[msga] {\n \twl := input[_]\n\twl.kind == \"CronJob\"\n\tcontainer = wl.spec.jobTemplate.spec.template.spec.containers[i]\n\tbegginingOfPath := \"spec.jobTemplate.spec.template.spec.\"\n path := isHostPort(container, i, begginingOfPath)\n msga := {\n\t\t\"alertMessage\": sprintf(\"Container: %v in %v: %v has Host-port\", [ container.name, wl.kind, wl.metadata.name]),\n\t\t\"packagename\": \"armo_builtins\",\n\t\t\"alertScore\": 7,\n\t\t\"failedPaths\": path,\n\t\t\"alertObject\": {\n\t\t\t\"k8sApiObjects\": [wl]\n\t\t}\n\t}\n}\n\n\n\nisHostPort(container, i, begginingOfPath) = path {\n\tpath = [sprintf(\"%vcontainers[%v].ports[%v].hostPort\", [begginingOfPath, format_int(i, 10), format_int(j, 10)]) | port = container.ports[j]; port.hostPort]\n\tcount(path) > 0\n}\n","resourceEnumerator":"","ruleLanguage":"Rego","match":[{"apiGroups":["*"],"apiVersions":["*"],"resources":["Deployment","ReplicaSet","DaemonSet","StatefulSet","Job","Pod","CronJob"]}],"ruleDependencies":[],"configInputs":null,"controlConfigInputs":null,"description":"fails if container has hostPort","remediation":"Make sure you do not configure hostPort for the container, if necessary use NodePort / ClusterIP","ruleQuery":"armo_builtins"}],"rulesIDs":[""],"baseScore":4}`
@@ -31,7 +31,7 @@ func MockFramework_0013() *reporthandling.Framework {
return fw
}
// MockFramework_0006_0013 mock control 0013 and control 0006 - "Non-root containers" and "Allowed hostPath"
// MockFramework_0006_0013 mock control 0013 and control 0006 - "Non-root containers" and "HostPath mount"
func MockFramework_0006_0013() *reporthandling.Framework {
fw := &reporthandling.Framework{
PortalBase: armotypes.PortalBase{

View File

@@ -28,12 +28,15 @@ spec:
tolerations:
# this toleration is to have the DaemonDet runnable on master nodes
# remove it if your masters can't run pods
- key: node-role.kubernetes.io/control-plane
operator: Exists
effect: NoSchedule
- key: node-role.kubernetes.io/master
operator: Exists
effect: NoSchedule
containers:
- name: host-sensor
image: quay.io/kubescape/host-scanner:v1.0.28
image: quay.io/kubescape/host-scanner:v1.0.32
securityContext:
privileged: true
readOnlyRootFilesystem: true
@@ -69,4 +72,4 @@ spec:
name: host-filesystem
hostNetwork: true
hostPID: true
hostIPC: true
hostIPC: true

View File

@@ -129,6 +129,12 @@ func (hsh *HostSensorHandler) GetKubeProxyInfo() ([]hostsensor.HostSensorDataEnv
return hsh.sendAllPodsHTTPGETRequest("/kubeProxyInfo", "KubeProxyInfo")
}
// return list of KubeProxyInfo
func (hsh *HostSensorHandler) GetControlPlaneInfo() ([]hostsensor.HostSensorDataEnvelope, error) {
// loop over pods and port-forward it to each of them
return hsh.sendAllPodsHTTPGETRequest("/controlPlaneInfo", ControlPlaneInfo)
}
// return list of KubeletCommandLine
func (hsh *HostSensorHandler) GetKubeletCommandLine() ([]hostsensor.HostSensorDataEnvelope, error) {
// loop over pods and port-forward it to each of them
@@ -269,6 +275,16 @@ func (hsh *HostSensorHandler) CollectResources() ([]hostsensor.HostSensorDataEnv
res = append(res, kcData...)
}
// GetControlPlaneInfo
kcData, err = hsh.GetControlPlaneInfo()
if err != nil {
addInfoToMap(ControlPlaneInfo, infoMap, err)
logger.L().Warning(err.Error())
}
if len(kcData) > 0 {
res = append(res, kcData...)
}
logger.L().Debug("Done reading information from host scanner")
return res, infoMap, nil
}

View File

@@ -15,6 +15,7 @@ var (
KubeletCommandLine = "KubeletCommandLine"
KubeletInfo = "KubeletInfo"
KubeProxyInfo = "KubeProxyInfo"
ControlPlaneInfo = "ControlPlaneInfo"
MapHostSensorResourceToApiGroup = map[string]string{
KubeletConfiguration: "hostdata.kubescape.cloud/v1beta0",
@@ -26,6 +27,7 @@ var (
LinuxKernelVariables: "hostdata.kubescape.cloud/v1beta0",
KubeletInfo: "hostdata.kubescape.cloud/v1beta0",
KubeProxyInfo: "hostdata.kubescape.cloud/v1beta0",
ControlPlaneInfo: "hostdata.kubescape.cloud/v1beta0",
}
)

View File

@@ -41,6 +41,8 @@ func (policyHandler *PolicyHandler) getPolicies(policyIdentifier []cautils.Polic
controlsInputs, err := policyHandler.getters.ControlsInputsGetter.GetControlsInputs(cautils.ClusterName)
if err == nil {
policiesAndResources.RegoInputData.PostureControlInputs = controlsInputs
} else {
logger.L().Error(err.Error())
}
cautils.StopSpinner()

View File

@@ -51,7 +51,7 @@ func (ksCivAdaptor *KSCivAdaptor) GetImageVulnerability(imageID *registryvulnera
pageNumber := 1
request := V2ListRequest{PageSize: &pageSize, PageNum: &pageNumber, InnerFilters: filter, OrderBy: "timestamp:desc"}
requestBody, _ := json.Marshal(request)
requestUrl := fmt.Sprintf("https://%s/api/v1/vulnerability/scanResultsDetails?customerGUID=%s", ksCivAdaptor.ksCloudAPI.GetApiURL(), ksCivAdaptor.ksCloudAPI.GetAccountID())
requestUrl := fmt.Sprintf("https://%s/api/v1/vulnerability/scanResultsDetails?customerGUID=%s", ksCivAdaptor.ksCloudAPI.GetCloudAPIURL(), ksCivAdaptor.ksCloudAPI.GetAccountID())
resp, err := ksCivAdaptor.ksCloudAPI.Post(requestUrl, map[string]string{"Content-Type": "application/json"}, requestBody)
if err != nil {

View File

@@ -14,7 +14,7 @@ func (armoCivAdaptor *KSCivAdaptor) getImageLastScanId(imageID *registryvulnerab
pageNumber := 1
request := V2ListRequest{PageSize: &pageSize, PageNum: &pageNumber, InnerFilters: filter, OrderBy: "timestamp:desc"}
requestBody, _ := json.Marshal(request)
requestUrl := fmt.Sprintf("https://%s/api/v1/vulnerability/scanResultsSumSummary?customerGUID=%s", armoCivAdaptor.ksCloudAPI.GetApiURL(), armoCivAdaptor.ksCloudAPI.GetAccountID())
requestUrl := fmt.Sprintf("https://%s/api/v1/vulnerability/scanResultsSumSummary?customerGUID=%s", armoCivAdaptor.ksCloudAPI.GetCloudAPIURL(), armoCivAdaptor.ksCloudAPI.GetAccountID())
resp, err := armoCivAdaptor.ksCloudAPI.Post(requestUrl, map[string]string{"Content-Type": "application/json"}, requestBody)
if err != nil {

View File

@@ -0,0 +1,33 @@
# GCP Adaptor
### How we add gcp adaptor
As there can be possiblities of use of multiple registries we check for each adaptor if we have required credentias. For every adaptor having credentials we append the adaptor to the adaptors slice.
Particularly for gcp, we frstly bring the `gcpCloudAPI` from the connector. We still haven't created a proper function that initiats the gcpCloudAPI with projectId, credentialsPath, credentialsCheck fields. We check for `credentialsCheck` bool which is set true when we have credentials(to be set when initializing the gcpCloudAPI)
### How we fetch vulnerabilities for images
Step 1:
Get container analysis client
For this we needs credentials of the service account. Out of few approaches here we are using [JSON key file](https://cloud.google.com/container-registry/docs/advanced-authentication#json-key) for credentials and path to this file should be stored in `credentialsPath`
Step 2:
Do ListOccurrenceRequest
For this we need the `projectID` and the `resourceUrl`. ProjectID should be provided by the users and resourceUrl is processed imageTag that we get from kubescape resources
Step 3:
Get Occurrence iterator
We use context and the request from the ListOccurenceRequest to get the iterators
### How we convert the response to Vulnerabilities
Response from the iterator has two type of kinds i.e. Discovery and Vulnerabilties and both has differnent struct
### How can this adaptor be used by the user
To know about GCR service accounts follow https://cloud.google.com/container-registry/docs/gcr-service-account
export variables
`export KS_GCP_CREDENTIALS_PATH=<path to service account credentials file>`
`export KS_GCP_PROJECT_ID=<your project ID>`

View File

@@ -0,0 +1,24 @@
package v1
import (
"github.com/kubescape/kubescape/v2/core/cautils/getter"
)
type GCPAdaptor struct {
GCPCloudAPI *getter.GCPCloudAPI
}
type Mock struct {
Name string
Notename string
CvssScore float32
CreatedTime int64
UpdatedTime int64
Type string
ShortDescription string
AffectedCPEURI string
AffectedPackage string
FixAvailable bool
AffectedVersion string
FixedVersion string
}

View File

@@ -0,0 +1,88 @@
package v1
import (
"fmt"
containeranalysis "cloud.google.com/go/containeranalysis/apiv1"
"github.com/kubescape/go-logger"
"github.com/kubescape/go-logger/helpers"
"github.com/kubescape/kubescape/v2/core/cautils/getter"
"github.com/kubescape/kubescape/v2/core/pkg/registryadaptors/registryvulnerabilities"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
grafeaspb "google.golang.org/genproto/googleapis/grafeas/v1"
)
func NewGCPAdaptor(GCPCloudAPI *getter.GCPCloudAPI) *GCPAdaptor {
return &GCPAdaptor{
GCPCloudAPI: GCPCloudAPI,
}
}
func (GCPAdaptor *GCPAdaptor) Login() error {
client, err := containeranalysis.NewClient(GCPAdaptor.GCPCloudAPI.GetContext(), option.WithCredentialsFile(GCPAdaptor.GCPCloudAPI.GetCredentialsPath()))
if err != nil {
return err
}
GCPAdaptor.GCPCloudAPI.SetClient(client)
return nil
}
func (GCPAdaptor *GCPAdaptor) GetImagesVulnerabilities(imageIDs []registryvulnerabilities.ContainerImageIdentifier) ([]registryvulnerabilities.ContainerImageVulnerabilityReport, error) {
resultList := make([]registryvulnerabilities.ContainerImageVulnerabilityReport, 0)
for _, imageID := range imageIDs {
result, err := GCPAdaptor.GetImageVulnerability(&imageID)
if err == nil {
resultList = append(resultList, *result)
} else {
logger.L().Debug("failed to get image vulnerabilities", helpers.String("image", imageID.Tag), helpers.Error(err))
}
}
return resultList, nil
}
func (GCPAdaptor *GCPAdaptor) GetImageVulnerability(imageID *registryvulnerabilities.ContainerImageIdentifier) (*registryvulnerabilities.ContainerImageVulnerabilityReport, error) {
resourceUrl := fmt.Sprintf("https://%s", imageID.Tag)
req := &grafeaspb.ListOccurrencesRequest{
Parent: fmt.Sprintf("projects/%s", GCPAdaptor.GCPCloudAPI.GetProjectID()),
Filter: fmt.Sprintf(`resourceUrl=%q`, resourceUrl),
}
it := GCPAdaptor.GCPCloudAPI.GetClient().GetGrafeasClient().ListOccurrences(GCPAdaptor.GCPCloudAPI.GetContext(), req)
occs := []*grafeaspb.Occurrence{}
var count int
for {
occ, err := it.Next()
if err == iterator.Done {
break
}
if err != nil {
return nil, err
}
occs = append(occs, occ)
count++
}
vulnerabilities := responseObjectToVulnerabilities(occs, count)
resultImageVulnerabilityReport := registryvulnerabilities.ContainerImageVulnerabilityReport{
ImageID: *imageID,
Vulnerabilities: vulnerabilities,
}
return &resultImageVulnerabilityReport, nil
}
func (GCPAdaptor *GCPAdaptor) DescribeAdaptor() string {
return "GCP image vulnerabilities scanner, docs: https://cloud.google.com/container-analysis/docs/container-analysis"
}
func (GCPAdaptor *GCPAdaptor) GetImagesInformation(imageIDs []registryvulnerabilities.ContainerImageIdentifier) ([]registryvulnerabilities.ContainerImageInformation, error) {
// TODO
return []registryvulnerabilities.ContainerImageInformation{}, nil
}
func (GCPAdaptor *GCPAdaptor) GetImagesScanStatus(imageIDs []registryvulnerabilities.ContainerImageIdentifier) ([]registryvulnerabilities.ContainerImageScanStatus, error) {
// TODO
return []registryvulnerabilities.ContainerImageScanStatus{}, nil
}

View File

@@ -0,0 +1,31 @@
package v1
import (
"testing"
"github.com/kubescape/kubescape/v2/core/pkg/registryadaptors/registryvulnerabilities"
"github.com/stretchr/testify/assert"
)
func TestSum(t *testing.T) {
var err error
var adaptor registryvulnerabilities.IContainerImageVulnerabilityAdaptor
adaptor, err = NewGCPAdaptorMock()
assert.NoError(t, err)
assert.NoError(t, adaptor.Login())
imageVulnerabilityReports, err := adaptor.GetImagesVulnerabilities([]registryvulnerabilities.ContainerImageIdentifier{{Tag: "gcr.io/myproject/nginx@sha256:1XXXXX"}, {Tag: "gcr.io/myproject/nginx@sha256:2XXXXX"}})
assert.NoError(t, err)
for i := range imageVulnerabilityReports {
var length int
if i == 0 {
length = 5
} else if i == 1 {
length = 3
}
assert.Equal(t, length, len(imageVulnerabilityReports[i].Vulnerabilities))
}
}

View File

@@ -0,0 +1,185 @@
package v1
import (
"github.com/kubescape/kubescape/v2/core/pkg/registryadaptors/registryvulnerabilities"
grafeaspb "google.golang.org/genproto/googleapis/grafeas/v1"
"google.golang.org/protobuf/types/known/timestamppb"
)
type GCPAdaptorMock struct {
resultList []registryvulnerabilities.ContainerImageVulnerabilityReport
}
func NewGCPAdaptorMock() (*GCPAdaptorMock, error) {
return &GCPAdaptorMock{}, nil
}
func (GCPAdaptorMock *GCPAdaptorMock) Login() error {
return nil
}
func (GCPAdaptorMock *GCPAdaptorMock) GetImagesVulnerabilities(imageIDs []registryvulnerabilities.ContainerImageIdentifier) ([]registryvulnerabilities.ContainerImageVulnerabilityReport, error) {
resultList := make([]registryvulnerabilities.ContainerImageVulnerabilityReport, 0)
for _, imageID := range imageIDs {
result, err := GCPAdaptorMock.GetImageVulnerability(&imageID)
if err == nil {
resultList = append(resultList, *result)
} else {
return nil, err
}
return resultList, nil
}
GCPAdaptorMock.resultList = resultList
return GCPAdaptorMock.resultList, nil
}
func (GCPAdaptorMock *GCPAdaptorMock) GetImageVulnerability(imageID *registryvulnerabilities.ContainerImageIdentifier) (*registryvulnerabilities.ContainerImageVulnerabilityReport, error) {
vulnerability := []*grafeaspb.Occurrence_Vulnerability{}
occurrence := []*grafeaspb.Occurrence{}
arr := GetMockData()
for i, _ := range arr {
if imageID.Tag == "gcr.io/myproject/nginx@sha256:2XXXXX" && i == 4 {
break
}
vulnerability = append(vulnerability, &grafeaspb.Occurrence_Vulnerability{
Vulnerability: &grafeaspb.VulnerabilityOccurrence{
Type: arr[i].Type,
CvssScore: arr[i].CvssScore,
ShortDescription: arr[i].ShortDescription,
PackageIssue: []*grafeaspb.VulnerabilityOccurrence_PackageIssue{
{
FixedVersion: &grafeaspb.Version{
FullName: arr[i].FixedVersion,
},
AffectedVersion: &grafeaspb.Version{
FullName: arr[i].AffectedVersion,
},
AffectedCpeUri: arr[i].AffectedCPEURI,
AffectedPackage: arr[i].AffectedPackage,
},
},
FixAvailable: arr[i].FixAvailable,
},
})
occurrence = append(occurrence, &grafeaspb.Occurrence{
Name: arr[i].Name,
Kind: grafeaspb.NoteKind_ATTESTATION,
NoteName: arr[i].Notename,
CreateTime: &timestamppb.Timestamp{
Seconds: arr[i].CreatedTime,
},
UpdateTime: &timestamppb.Timestamp{
Seconds: arr[i].UpdatedTime,
},
Details: vulnerability[i],
})
}
vulnerabilities := responseObjectToVulnerabilities(occurrence, 5)
resultImageVulnerabilityReport := registryvulnerabilities.ContainerImageVulnerabilityReport{
ImageID: *imageID,
Vulnerabilities: vulnerabilities,
}
return &resultImageVulnerabilityReport, nil
}
func (GCPAdaptorMock *GCPAdaptorMock) DescribeAdaptor() string {
// TODO
return ""
}
func (GCPAdaptorMock *GCPAdaptorMock) GetImagesInformation(imageIDs []registryvulnerabilities.ContainerImageIdentifier) ([]registryvulnerabilities.ContainerImageInformation, error) {
// TODO
return []registryvulnerabilities.ContainerImageInformation{}, nil
}
func (GCPAdaptorMock *GCPAdaptorMock) GetImagesScanStatus(imageIDs []registryvulnerabilities.ContainerImageIdentifier) ([]registryvulnerabilities.ContainerImageScanStatus, error) {
// TODO
return []registryvulnerabilities.ContainerImageScanStatus{}, nil
}
//==============================================================================================================================
//==============================================================================================================================
//==============================================================================================================================
func GetMockData() []Mock {
arr := []Mock{
{
Name: "projects/stable-furnace-356005/occurrences/41fd9fec-6fab-4531-a4ee-e7b97d518554",
Notename: "projects/goog-vulnz/notes/CVE-2009-4487",
CvssScore: 6.8,
CreatedTime: 1661061853,
UpdatedTime: 1661061853,
Type: "OS",
ShortDescription: "CVE-2009-4487",
AffectedCPEURI: "cpe:/o:debian:debian_linux:11",
AffectedPackage: "nginx",
FixAvailable: true,
AffectedVersion: "1.23.1-1~bullseye",
FixedVersion: "",
},
{
Name: "projects/stable-furnace-356005/occurrences/b28fa29f-5c2b-45c7-9727-2f1f02ed1957",
Notename: "projects/goog-vulnz/notes/CVE-2017-17740",
CvssScore: 2.3,
CreatedTime: 3237628,
UpdatedTime: 5989893,
Type: "OS",
ShortDescription: "CVE-2017-17740",
AffectedCPEURI: "cpe:/o:debian:debian_linux:11",
AffectedPackage: "openldap",
FixAvailable: false,
AffectedVersion: "1.3.5",
FixedVersion: "1.3.5",
},
{
Name: "projects/stable-furnace-356005/occurrences/b28fa29f-5c2b-45c7-9727-2f1f02ed1957",
Notename: "projects/goog-vulnz/notes/CVE-2017-17740",
CvssScore: 2.3,
CreatedTime: 3237628,
UpdatedTime: 5989893,
Type: "OS",
ShortDescription: "CVE-2017-17740",
AffectedCPEURI: "cpe:/o:debian:debian_linux:11",
AffectedPackage: "openldap",
FixAvailable: false,
AffectedVersion: "1.3.5",
FixedVersion: "1.3.5",
},
{
Name: "projects/stable-furnace-356005/occurrences/b28fa29f-5c2b-45c7-9727-2f1f02ed1957",
Notename: "projects/goog-vulnz/notes/CVE-2017-17740",
CvssScore: 2.3,
CreatedTime: 3237628,
UpdatedTime: 5989893,
Type: "OS",
ShortDescription: "CVE-2017-17740",
AffectedCPEURI: "cpe:/o:debian:debian_linux:11",
AffectedPackage: "openldap",
FixAvailable: false,
AffectedVersion: "1.3.5",
FixedVersion: "1.3.5",
},
{
Name: "projects/stable-furnace-356005/occurrences/b28fa29f-5c2b-45c7-9727-2f1f02ed1957",
Notename: "projects/goog-vulnz/notes/CVE-2017-17740",
CvssScore: 2.3,
CreatedTime: 3237628,
UpdatedTime: 5989893,
Type: "OS",
ShortDescription: "CVE-2017-17740",
AffectedCPEURI: "cpe:/o:debian:debian_linux:11",
AffectedPackage: "openldap",
FixAvailable: false,
AffectedVersion: "1.3.5",
FixedVersion: "1.3.5",
},
}
return arr
}

View File

@@ -0,0 +1,36 @@
package v1
import (
"github.com/kubescape/kubescape/v2/core/pkg/registryadaptors/registryvulnerabilities"
grafeaspb "google.golang.org/genproto/googleapis/grafeas/v1"
)
func responseObjectToVulnerabilities(vulnerabilityList []*grafeaspb.Occurrence, count int) []registryvulnerabilities.Vulnerability {
vulnerabilities := make([]registryvulnerabilities.Vulnerability, count)
for i, vulnerabilityEntry := range vulnerabilityList {
if vulnerabilityEntry.GetKind().String() != "DISCOVERY" {
vulnerabilities[i].Name = vulnerabilityEntry.Name
vulnerabilities[i].NoteName = vulnerabilityEntry.NoteName
vulnerabilities[i].CreateTime = vulnerabilityEntry.CreateTime.AsTime()
vulnerabilities[i].UpdateTime = vulnerabilityEntry.UpdateTime.AsTime()
vulnerabilities[i].CVSS = vulnerabilityEntry.GetVulnerability().CvssScore
vulnerabilities[i].AffectedCPEURI = vulnerabilityEntry.GetVulnerability().PackageIssue[0].AffectedCpeUri
vulnerabilities[i].AffectedPackage = vulnerabilityEntry.GetVulnerability().PackageIssue[0].AffectedPackage
vulnerabilities[i].AffectedVersion = vulnerabilityEntry.GetVulnerability().PackageIssue[0].AffectedVersion.FullName
vulnerabilities[i].FixedVersion = vulnerabilityEntry.GetVulnerability().PackageIssue[0].FixedVersion.FullName
vulnerabilities[i].FixedCPEURI = vulnerabilityEntry.GetVulnerability().PackageIssue[0].FixedCpeUri
vulnerabilities[i].FixedPackege = vulnerabilityEntry.GetVulnerability().PackageIssue[0].FixedPackage
vulnerabilities[i].FixAvailablePackage = vulnerabilityEntry.GetVulnerability().PackageIssue[0].GetFixAvailable()
vulnerabilities[i].PackageType = vulnerabilityEntry.GetVulnerability().PackageIssue[0].PackageType
vulnerabilities[i].EffectiveSeverityPackage = vulnerabilityEntry.GetVulnerability().PackageIssue[0].EffectiveSeverity.String()
vulnerabilities[i].AffectedPackage = vulnerabilityEntry.GetVulnerability().PackageIssue[0].AffectedPackage
vulnerabilities[i].Severity = vulnerabilityEntry.GetVulnerability().Severity.Enum().String()
vulnerabilities[i].ShortDescription = vulnerabilityEntry.GetVulnerability().ShortDescription
vulnerabilities[i].LongDescription = vulnerabilityEntry.GetVulnerability().LongDescription
} else {
vulnerabilities[i].Description = vulnerabilityEntry.GetDiscovery().String()
}
}
return vulnerabilities
}

View File

@@ -28,19 +28,36 @@ type Categories struct {
}
type Vulnerability struct {
Name string `json:"name"`
RelatedPackageName string `json:"packageName"`
PackageVersion string `json:"packageVersion"`
Link string `json:"link"`
Description string `json:"description"`
Severity string `json:"severity"`
Metadata interface{} `json:"metadata"`
Fixes []FixedIn `json:"fixedIn"`
Relevancy string `json:"relevant"` // use the related enum
UrgentCount int `json:"urgent"`
NeglectedCount int `json:"neglected"`
HealthStatus string `json:"healthStatus"`
Categories Categories `json:"categories"`
Name string `json:"name"`
RelatedPackageName string `json:"packageName"`
PackageVersion string `json:"packageVersion"`
Link string `json:"link"`
Description string `json:"description"`
Severity string `json:"severity"`
Metadata interface{} `json:"metadata"`
Fixes []FixedIn `json:"fixedIn"`
Relevancy string `json:"relevant"` // use the related enum
UrgentCount int `json:"urgent"`
NeglectedCount int `json:"neglected"`
HealthStatus string `json:"healthStatus"`
Categories Categories `json:"categories"`
NoteName string `json:",omitempty"`
CreateTime time.Time `json:",omitempty"`
UpdateTime time.Time `json:",omitempty"` // Vulnerablity started
CVSS float32 `json:",omitempty"` // other cvss versions are available
AffectedCPEURI string `json:",omitempty"` // Package issue
AffectedPackage string `json:",omitempty"`
AffectedVersion string `json:",omitempty"`
FixedVersion string `json:",omitempty"`
FixedCPEURI string `json:",omitempty"`
FixedPackege string `json:",omitempty"`
FixAvailablePackage bool `json:",omitempty"`
PackageType string `json:",omitempty"`
EffectiveSeverityPackage string `json:",omitempty"`
ShortDescription string `json:",omitempty"` // Package issue ends
LongDescription string `json:",omitempty"`
EffectiveSeverity string `json:",omitempty"`
FixAvailable bool `json:",omitempty"`
}
type ContainerImageVulnerabilityReport struct {

View File

@@ -10,6 +10,7 @@ import (
type IFieldSelector interface {
GetNamespacesSelectors(*schema.GroupVersionResource) []string
GetClusterScope(*schema.GroupVersionResource) bool
}
type EmptySelector struct {
@@ -19,6 +20,10 @@ func (es *EmptySelector) GetNamespacesSelectors(resource *schema.GroupVersionRes
return []string{""} //
}
func (es *EmptySelector) GetClusterScope(*schema.GroupVersionResource) bool {
return true
}
type ExcludeSelector struct {
namespace string
}
@@ -27,6 +32,14 @@ func NewExcludeSelector(ns string) *ExcludeSelector {
return &ExcludeSelector{namespace: ns}
}
func (es *ExcludeSelector) GetClusterScope(resource *schema.GroupVersionResource) bool {
// for selector, 'namespace' is in Namespaced scope
if resource.Resource == "namespaces" {
return true
}
return false
}
type IncludeSelector struct {
namespace string
}
@@ -34,6 +47,15 @@ type IncludeSelector struct {
func NewIncludeSelector(ns string) *IncludeSelector {
return &IncludeSelector{namespace: ns}
}
func (is *IncludeSelector) GetClusterScope(resource *schema.GroupVersionResource) bool {
// for selector, 'namespace' is in Namespaced scope
if resource.Resource == "namespaces" {
return true
}
return false
}
func (es *ExcludeSelector) GetNamespacesSelectors(resource *schema.GroupVersionResource) []string {
fieldSelectors := ""
for _, n := range strings.Split(es.namespace, ",") {

View File

@@ -84,7 +84,7 @@ func (k8sHandler *K8sResourceHandler) GetResources(sessionObj *cautils.OPASessio
imgVulnResources := cautils.MapImageVulnResources(ksResourceMap)
// check that controls use image vulnerability resources
if false { //len(imgVulnResources) > 0 {
if len(imgVulnResources) > 0 {
logger.L().Info("Requesting images vulnerabilities results")
cautils.StartSpinner()
if err := k8sHandler.registryAdaptors.collectImagesVulnerabilities(k8sResourcesMap, allResources, ksResourceMap); err != nil {
@@ -134,8 +134,6 @@ func (k8sHandler *K8sResourceHandler) GetResources(sessionObj *cautils.OPASessio
// check that controls use cloud resources
if len(cloudResources) > 0 {
logger.L().Info("Requesting cloud provider data")
cautils.StartSpinner()
provider, err := getCloudProviderDescription(allResources, ksResourceMap)
if err != nil {
cautils.SetInfoMapForResources(err.Error(), cloudResources, sessionObj.InfoMap)
@@ -146,13 +144,29 @@ func (k8sHandler *K8sResourceHandler) GetResources(sessionObj *cautils.OPASessio
sessionObj.Metadata.ContextMetadata.ClusterContextMetadata.CloudProvider = provider
}
}
cautils.StopSpinner()
logger.L().Info("Requested cloud provider data")
// api server info resource
err = k8sHandler.collectAPIServerInfoResource(allResources, ksResourceMap)
if err != nil {
logger.L().Warning("failed to collect api server info resource", helpers.Error(err))
}
}
return k8sResourcesMap, allResources, ksResourceMap, nil
}
func (k8sHandler *K8sResourceHandler) collectAPIServerInfoResource(allResources map[string]workloadinterface.IMetadata, ksResourceMap *cautils.KSResources) error {
clusterAPIServerInfo, err := k8sHandler.k8s.DiscoveryClient.ServerVersion()
if err != nil {
return err
}
resource := cloudsupport.NewApiServerVersionInfo(clusterAPIServerInfo)
allResources[resource.GetID()] = resource
(*ksResourceMap)[fmt.Sprintf("%s/%s", resource.GetApiVersion(), resource.GetKind())] = []string{resource.GetID()}
return nil
}
func (k8sHandler *K8sResourceHandler) GetClusterAPIServerInfo() *version.Info {
clusterAPIServerInfo, err := k8sHandler.k8s.DiscoveryClient.ServerVersion()
if err != nil {
@@ -230,10 +244,14 @@ func (k8sHandler *K8sResourceHandler) pullSingleResource(resource *schema.GroupV
// set dynamic object
var clientResource dynamic.ResourceInterface
if namespace != "" && k8sinterface.IsNamespaceScope(resource) {
clientResource = k8sHandler.k8s.DynamicClient.Resource(*resource).Namespace(namespace)
} else {
if namespace != "" {
clientResource = k8sHandler.k8s.DynamicClient.Resource(*resource)
} else if k8sinterface.IsNamespaceScope(resource) {
clientResource = k8sHandler.k8s.DynamicClient.Resource(*resource).Namespace(namespace)
} else if k8sHandler.fieldSelector.GetClusterScope(*&resource) {
clientResource = k8sHandler.k8s.DynamicClient.Resource(*resource)
} else {
continue
}
// list resources

View File

@@ -22,6 +22,7 @@ var (
ImageVulnerabilities = "ImageVulnerabilities"
KubeletInfo = "KubeletInfo"
KubeProxyInfo = "KubeProxyInfo"
ControlPlaneInfo = "ControlPlaneInfo"
MapResourceToApiGroup = map[string]string{
KubeletConfiguration: "hostdata.kubescape.cloud/v1beta0",
@@ -33,6 +34,7 @@ var (
LinuxKernelVariables: "hostdata.kubescape.cloud/v1beta0",
KubeletInfo: "hostdata.kubescape.cloud/v1beta0",
KubeProxyInfo: "hostdata.kubescape.cloud/v1beta0",
ControlPlaneInfo: "hostdata.kubescape.cloud/v1beta0",
}
MapResourceToApiGroupVuln = map[string][]string{
ImageVulnerabilities: {"armo.vuln.images/v1", "image.vulnscan.com/v1"}}

View File

@@ -8,6 +8,7 @@ import (
"github.com/kubescape/k8s-interface/workloadinterface"
"github.com/kubescape/kubescape/v2/core/cautils"
"github.com/kubescape/kubescape/v2/core/cautils/getter"
gcpadaptorv1 "github.com/kubescape/kubescape/v2/core/pkg/registryadaptors/gcp/v1"
armosecadaptorv1 "github.com/kubescape/kubescape/v2/core/pkg/registryadaptors/armosec/v1"
"github.com/kubescape/kubescape/v2/core/pkg/registryadaptors/registryvulnerabilities"
@@ -158,5 +159,12 @@ func listAdaptores() ([]registryvulnerabilities.IContainerImageVulnerabilityAdap
}
}
gcpCloudAPI := getter.GetGlobalGCPCloudAPIConnector()
if gcpCloudAPI != nil {
if gcpCloudAPI.GetCredentialsCheck() {
adaptors = append(adaptors, gcpadaptorv1.NewGCPAdaptor(getter.GetGlobalGCPCloudAPIConnector()))
}
}
return adaptors, nil
}

View File

@@ -13,6 +13,10 @@ var (
urlD = "https://raw.githubusercontent.com/kubescape/kubescape/master/examples/online-boutique/adservice.yaml"
)
/*
TODO: tests were commented out due to actual http calls ; http calls should be mocked.
func TestScanRepository(t *testing.T) {
{
files, err := ScanRepository(urlA, "")
@@ -112,6 +116,7 @@ func TestGithubGetYamlFromTree(t *testing.T) {
assert.Equal(t, 12, len(files))
}
}
*/
func TestGithubParse(t *testing.T) {
{

View File

@@ -2,12 +2,11 @@ package resourcehandler
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestLoadResourcesFromUrl(t *testing.T) {
{
//TODO: tests were commented out due to actual http calls ; http calls should be mocked.
/*{
workloads, err := loadResourcesFromUrl([]string{"https://github.com/kubescape/kubescape/tree/master/examples/online-boutique"})
assert.NoError(t, err)
assert.Equal(t, 12, len(workloads))
@@ -62,5 +61,5 @@ func TestLoadResourcesFromUrl(t *testing.T) {
assert.Equal(t, "/v1//Service/adservice", w[1].GetID())
}
}
}
}*/
}

View File

@@ -3,6 +3,8 @@ package resourcesprioritization
import (
"fmt"
logger "github.com/kubescape/go-logger"
"github.com/kubescape/go-logger/helpers"
"github.com/kubescape/k8s-interface/workloadinterface"
"github.com/kubescape/kubescape/v2/core/cautils"
"github.com/kubescape/kubescape/v2/core/cautils/getter"
@@ -55,7 +57,8 @@ func (handler *ResourcesPrioritizationHandler) PrioritizeResources(sessionObj *c
resourcePriorityVector := []prioritization.ControlsVector{}
resource, exist := sessionObj.AllResources[resourceId]
if !exist {
return fmt.Errorf("expected to find resource id '%s' in scanned resources map", resourceId)
logger.L().Error("resource not found in resources map", helpers.String("resource ID", resourceId))
continue
}
workload := workloadinterface.NewWorkloadObj(resource.GetObject())

View File

@@ -0,0 +1,94 @@
package locationresolver
import (
"errors"
"fmt"
"io"
"os"
"regexp"
"strings"
"github.com/kubescape/go-logger"
"github.com/mikefarah/yq/v4/pkg/yqlib"
"gopkg.in/op/go-logging.v1"
"gopkg.in/yaml.v3"
)
type FixPathLocationResolver struct {
yqlibEvaluator yqlib.Evaluator
yamlPath string
yamlNodes []*yaml.Node
}
type Location struct {
Line int
Column int
}
func NewFixPathLocationResolver(yamlPath string) (*FixPathLocationResolver, error) {
file, err := os.Open(yamlPath)
if err != nil {
return nil, err
}
defer file.Close()
yamlNodes := make([]*yaml.Node, 0)
yamlDecoder := yaml.NewDecoder(file)
for {
var yamlNode yaml.Node
err = yamlDecoder.Decode(&yamlNode)
if errors.Is(err, io.EOF) {
break
} else if err != nil {
return nil, err
} else {
yamlNodes = append(yamlNodes, &yamlNode)
}
}
evaluator := yqlib.NewAllAtOnceEvaluator()
backendLoggerLeveled := logging.AddModuleLevel(logging.NewLogBackend(logger.L().GetWriter(), "", 0))
backendLoggerLeveled.SetLevel(logging.ERROR, "")
yqlib.GetLogger().SetBackend(backendLoggerLeveled)
return &FixPathLocationResolver{
yamlPath: yamlPath,
yqlibEvaluator: evaluator,
yamlNodes: yamlNodes,
}, nil
}
func (l *FixPathLocationResolver) ResolveLocation(fixPath string, nodeIndex int) (Location, error) {
if nodeIndex >= len(l.yamlNodes) {
return Location{}, fmt.Errorf("node index [%d] out of range [%d]", nodeIndex, len(l.yamlNodes))
}
yamlExpression := FixPathToValidYamlExpression(fixPath)
for strings.HasPrefix(yamlExpression, ".") && len(yamlExpression) > 1 {
candidateNodes, err := l.yqlibEvaluator.EvaluateNodes(yamlExpression, l.yamlNodes[nodeIndex])
if err != nil {
return Location{}, err
}
candidateNode := candidateNodes.Back().Value.(*yqlib.CandidateNode).Node
if candidateNode.Line != 0 || len(yamlExpression) <= 1 {
return Location{Line: candidateNode.Line, Column: candidateNode.Column}, nil
}
// for non-existent yaml expressions, remove the last part of the expression and try again
yamlExpression = regexp.MustCompile(`(.*)(\.[^.]*)`).ReplaceAllString(yamlExpression, `${1}`)
}
return Location{}, nil
}
func FixPathToValidYamlExpression(fixPath string) string {
// remove everything after the first =
yamlExpression := regexp.MustCompile(`(.*)=.*`).ReplaceAllString(fixPath, `${1}`)
// add a dot for the root node
yamlExpression = "." + yamlExpression
return yamlExpression
}

View File

@@ -0,0 +1,64 @@
package locationresolver
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
)
func onlineBoutiquePath() string {
o, _ := os.Getwd()
return filepath.Join(filepath.Dir(o), "..", "..", "..", "examples", "online-boutique")
}
func TestResolveLocation(t *testing.T) {
yamlFilePath := filepath.Join(onlineBoutiquePath(), "adservice.yaml")
fixPathToExpectedLineAndColumn := map[string]Location{
"spec.template.spec.containers[0].securityContext.readOnlyRootFilesystem=true": {Line: 31, Column: 9},
"spec.template.spec.containers[0].securityContext.runAsNonRoot=true": {Line: 31, Column: 9},
"spec.template.spec.containers[0].securityContext.allowPrivilegeEscalation=false": {Line: 31, Column: 9},
"spec.template.spec.containers[0].securityContext.capabilities.drop=NET_RAW": {Line: 31, Column: 9},
"spec.template.spec.containers[0].securityContext.seLinuxOptions=YOUR_VALUE": {Line: 31, Column: 9},
"spec.template.spec.containers[0].securityContext.seccompProfile=YOUR_VALUE": {Line: 31, Column: 9},
"spec.template.spec.securityContext.runAsNonRoot=true": {Line: 28, Column: 7},
"spec.template.spec.securityContext.allowPrivilegeEscalation=false": {Line: 28, Column: 7},
"spec.template.spec.containers[0].securityContext.seccompProfile.type=RuntimeDefault": {Line: 31, Column: 9},
"spec.template.spec.containers[0].image": {Line: 32, Column: 16},
"spec.template.spec.containers[0].seccompProfile=YOUR_VALUE": {Line: 31, Column: 9},
"spec.template.spec.containers[0].seLinuxOptions=YOUR_VALUE": {Line: 31, Column: 9},
"spec.template.spec.containers[0].capabilities.drop=YOUR_VALUE": {Line: 31, Column: 9},
"metadata.namespace=YOUR_NAMESPACE": {Line: 18, Column: 3},
"metadata.labels=YOUR_VALUE": {Line: 18, Column: 3},
"spec.template.metadata.labels=YOUR_VALUE": {Line: 26, Column: 9},
"spec.template.spec.containers[0].resources.limits.cpu=YOUR_VALUE": {Line: 49, Column: 18},
}
resolver, _ := NewFixPathLocationResolver(yamlFilePath)
for fixPath, expected := range fixPathToExpectedLineAndColumn {
location, err := resolver.ResolveLocation(fixPath, 0)
assert.NoError(t, err)
assert.Equalf(t, expected.Line, location.Line, "fixPath %s, expected line: %d, actual line: %d", fixPath, expected.Line, location.Line)
assert.Equalf(t, expected.Column, location.Column, "fixPath %s, expected column: %d, actual column: %d", fixPath, expected.Column, location.Column)
}
fixPathToExpectedLineAndColumn = map[string]Location{
"metadata.namespace=YOUR_NAMESPACE": {Line: 65, Column: 3},
"metadata.labels=YOUR_VALUE": {Line: 65, Column: 3},
}
for fixPath, expected := range fixPathToExpectedLineAndColumn {
location, err := resolver.ResolveLocation(fixPath, 1)
assert.NoError(t, err)
assert.Equalf(t, expected.Line, location.Line, "fixPath %s, expected line: %d, actual line: %d", fixPath, expected.Line, location.Line)
assert.Equalf(t, expected.Column, location.Column, "fixPath %s, expected column: %d, actual column: %d", fixPath, expected.Column, location.Column)
}
_, err := resolver.ResolveLocation("some invalid string as an input", 0)
assert.ErrorContains(t, err, "invalid input")
}

View File

@@ -18,6 +18,7 @@ const (
PrometheusFormat string = "prometheus"
PdfFormat string = "pdf"
HtmlFormat string = "html"
SARIFFormat string = "sarif"
)
type IPrinter interface {

View File

@@ -173,7 +173,7 @@ func failedControlsToFailureMessage(results *cautils.OPASessionObj, controls []r
msg += fmt.Sprintf("Test: %s\n", control.GetName())
msg += fmt.Sprintf("Severity: %s\n", apis.ControlSeverityToString(control.GetScoreFactor()))
msg += fmt.Sprintf("Remediation: %s\n", control.GetRemediation())
msg += fmt.Sprintf("Link: %s\n", getControlLink(control.GetID()))
msg += fmt.Sprintf("Link: %s\n", cautils.GetControlLink(control.GetID()))
if failedPaths := failedPathsToString(&c); len(failedPaths) > 0 {
msg += fmt.Sprintf("Failed paths: \n - %s\n", strings.Join(failedPaths, "\n - "))
}

View File

@@ -4,7 +4,6 @@ import (
"fmt"
"os"
"sort"
"strings"
"github.com/enescakir/emoji"
"github.com/kubescape/k8s-interface/workloadinterface"
@@ -84,7 +83,7 @@ func (prettyPrinter *PrettyPrinter) printSummary(controlName string, controlSumm
}
func (prettyPrinter *PrettyPrinter) printTitle(controlSummary reportsummary.IControlSummary) {
cautils.InfoDisplay(prettyPrinter.writer, "[control: %s - %s] ", controlSummary.GetName(), getControlLink(controlSummary.GetID()))
cautils.InfoDisplay(prettyPrinter.writer, "[control: %s - %s] ", controlSummary.GetName(), cautils.GetControlLink(controlSummary.GetID()))
switch controlSummary.GetStatus().Status() {
case apis.StatusSkipped:
cautils.InfoDisplay(prettyPrinter.writer, "skipped %v\n", emoji.ConfusedFace)
@@ -255,10 +254,6 @@ func frameworksScoresToString(frameworks []reportsummary.IFrameworkSummary) stri
return ""
}
func getControlLink(controlID string) string {
return fmt.Sprintf("https://hub.armosec.io/docs/%s", strings.ToLower(controlID))
}
// renderSeverityCountersSummary renders the string that reports severity counters summary
func renderSeverityCountersSummary(counters reportsummary.ISeverityCounters) string {
critical := counters.NumberOfResourcesWithCriticalSeverity()

View File

@@ -289,7 +289,7 @@ func (m *Metrics) setRiskScores(summaryDetails *reportsummary.SummaryDetails) {
controlName: control.GetName(),
controlID: control.GetID(),
riskScore: cautils.Float32ToInt(control.GetScore()),
link: getControlLink(control.GetID()),
link: cautils.GetControlLink(control.GetID()),
severity: apis.ControlSeverityToString(control.GetScoreFactor()),
remediation: control.GetRemediation(),
}

View File

@@ -73,7 +73,7 @@ func generateResourceRows(controls []resourcesresults.ResourceAssociatedControl,
continue
}
row[resourceColumnURL] = fmt.Sprintf("https://hub.armosec.io/docs/%s", strings.ToLower(controls[i].GetID()))
row[resourceColumnURL] = cautils.GetControlLink(controls[i].GetID())
row[resourceColumnPath] = strings.Join(append(failedPathsToString(&controls[i]), fixPathsToString(&controls[i])...), "\n")
row[resourceColumnName] = controls[i].GetName()

View File

@@ -0,0 +1,204 @@
package v2
import (
"fmt"
"os"
"path"
"path/filepath"
"strconv"
"strings"
logger "github.com/kubescape/go-logger"
"github.com/kubescape/go-logger/helpers"
"github.com/kubescape/kubescape/v2/core/cautils"
"github.com/kubescape/kubescape/v2/core/pkg/resultshandling/locationresolver"
"github.com/kubescape/kubescape/v2/core/pkg/resultshandling/printer"
"github.com/kubescape/opa-utils/objectsenvelopes/localworkload"
"github.com/kubescape/opa-utils/reporthandling/results/v1/reportsummary"
"github.com/kubescape/opa-utils/reporthandling/results/v1/resourcesresults"
v2 "github.com/kubescape/opa-utils/reporthandling/v2"
"github.com/owenrumney/go-sarif/v2/sarif"
)
const (
sarifOutputFile = "report"
sarifOutputExt = ".sarif"
toolName = "kubescape"
toolInfoURI = "https://armosec.io"
)
// sarifSeverityLevel is a SARIF-specific severity level for Rules and Results
type sarifSeverityLevel string
const (
sarifSeverityLevelNote sarifSeverityLevel = "note"
sarifSeverityLevelWarning sarifSeverityLevel = "warning"
sarifSeverityLevelError sarifSeverityLevel = "error"
)
// scoreFactorToSARIFSeverityLevel returns a SARIF severity level that matches
// a given Kubescape severity score
func scoreFactorToSARIFSeverityLevel(score float32) sarifSeverityLevel {
switch {
case score >= 9.0:
return sarifSeverityLevelError
case score >= 4.0:
return sarifSeverityLevelWarning
}
return sarifSeverityLevelNote
}
// SARIFPrinter is a printer that emits the report in the SARIF format
type SARIFPrinter struct {
// outputFile is the name of the output file
writer *os.File
}
// NewSARIFPrinter returns a new SARIF printer instance
func NewSARIFPrinter() *SARIFPrinter {
return &SARIFPrinter{}
}
func (sp *SARIFPrinter) Score(score float32) {
return
}
func (sp *SARIFPrinter) SetWriter(outputFile string) {
if outputFile == "" {
outputFile = sarifOutputFile
}
if filepath.Ext(strings.TrimSpace(outputFile)) != sarifOutputExt {
outputFile = outputFile + sarifOutputExt
}
sp.writer = printer.GetWriter(outputFile)
}
// addRule adds a rule description to the scan run based on the given control summary
func (sp *SARIFPrinter) addRule(scanRun *sarif.Run, control reportsummary.IControlSummary) {
controlSARIFSeverity := string(scoreFactorToSARIFSeverityLevel(control.GetScoreFactor()))
configuration := sarif.NewReportingConfiguration().WithLevel(controlSARIFSeverity)
scanRun.AddRule(control.GetID()).
WithDefaultConfiguration(configuration).
WithShortDescription(sarif.NewMultiformatMessageString(control.GetName())).
WithFullDescription(sarif.NewMultiformatMessageString(control.GetDescription())).
WithHelp(sarif.NewMultiformatMessageString(sp.generateRemediationMessage(control)))
}
// addResult adds a result of checking a rule to the scan run based on the given control summary
func (sp *SARIFPrinter) addResult(scanRun *sarif.Run, ctl reportsummary.IControlSummary, filepath string, location locationresolver.Location) {
scanRun.CreateResultForRule(ctl.GetID()).
WithMessage(sarif.NewTextMessage(ctl.GetDescription())).
AddLocation(
sarif.NewLocationWithPhysicalLocation(
sarif.NewPhysicalLocation().
WithArtifactLocation(
sarif.NewSimpleArtifactLocation(filepath),
).WithRegion(
sarif.NewRegion().WithStartLine(location.Line).WithStartColumn(location.Column),
),
),
)
}
func (sp *SARIFPrinter) ActionPrint(opaSessionObj *cautils.OPASessionObj) {
report, err := sarif.New(sarif.Version210)
if err != nil {
panic(err)
}
run := sarif.NewRunWithInformationURI(toolName, toolInfoURI)
basePath := getBasePathFromMetadata(*opaSessionObj)
for resourceID, result := range opaSessionObj.ResourcesResult {
if result.GetStatus(nil).IsFailed() {
resourceSource := opaSessionObj.ResourceSource[resourceID]
filepath := resourceSource.RelativePath
// Github Code Scanning considers results not associated to a file path meaningless and invalid when uploading
if filepath == "" || basePath == "" {
continue
}
rsrcAbsPath := path.Join(basePath, filepath)
locationResolver, err := locationresolver.NewFixPathLocationResolver(rsrcAbsPath)
if err != nil {
logger.L().Debug("failed to create location resolver", helpers.Error(err))
}
for _, ac := range result.AssociatedControls {
if ac.GetStatus(nil).IsFailed() {
ctl := opaSessionObj.Report.SummaryDetails.Controls.GetControl(reportsummary.EControlCriteriaID, ac.GetID())
location := sp.resolveFixLocation(opaSessionObj, locationResolver, &ac, resourceID)
sp.addRule(run, ctl)
sp.addResult(run, ctl, filepath, location)
}
}
}
}
report.AddRun(run)
report.PrettyWrite(sp.writer)
}
func (sp *SARIFPrinter) resolveFixLocation(opaSessionObj *cautils.OPASessionObj, locationResolver *locationresolver.FixPathLocationResolver, ac *resourcesresults.ResourceAssociatedControl, resourceID string) locationresolver.Location {
defaultLocation := locationresolver.Location{Line: 1, Column: 1}
if locationResolver == nil {
return defaultLocation
}
fixPaths := failedPathsToString(ac)
if len(fixPaths) == 0 {
fixPaths = fixPathsToString(ac)
}
var fixPath string
if len(fixPaths) > 0 {
fixPath = fixPaths[0]
}
var location locationresolver.Location
if fixPath == "" {
return defaultLocation
}
resource := opaSessionObj.AllResources[resourceID]
localworkload, ok := resource.(*localworkload.LocalWorkload)
if !ok {
return defaultLocation
}
splittedPath := strings.Split(localworkload.GetPath(), ":")
if len(splittedPath) <= 1 {
return defaultLocation
}
docIndex, _ := strconv.Atoi(splittedPath[1])
location, _ = locationResolver.ResolveLocation(fixPath, docIndex)
if location.Line == 0 {
return defaultLocation
}
return location
}
func getBasePathFromMetadata(opaSessionObj cautils.OPASessionObj) string {
if opaSessionObj.Metadata.ScanMetadata.ScanningTarget == v2.GitLocal {
return opaSessionObj.Metadata.ContextMetadata.RepoContextMetadata.LocalRootPath
}
if opaSessionObj.Metadata.ScanMetadata.ScanningTarget == v2.Directory {
return opaSessionObj.Metadata.ContextMetadata.DirectoryContextMetadata.BasePath
}
return ""
}
// generateRemediationMessage generates a remediation message for the given control summary
func (sp *SARIFPrinter) generateRemediationMessage(control reportsummary.IControlSummary) string {
return fmt.Sprintf("Remediation: %s", control.GetRemediation())
}

View File

@@ -0,0 +1,27 @@
package v2
import "testing"
func Test_scoreToSeverityLevel(t *testing.T) {
tc := []struct {
Name string
ScoreFactor float32
ExpectedSARIFLevel sarifSeverityLevel
}{
{"Score factor 1.0 should map to 'note' SARIF level", 1.0, sarifSeverityLevelNote},
{"Score facore 4.0 should map to 'warning' SARIF level", 4.0, sarifSeverityLevelWarning},
{"Score facore 7.0 should map to 'warning' SARIF level", 7.0, sarifSeverityLevelWarning},
{"Score facore 9.0 should map to 'error' SARIF level", 9.0, sarifSeverityLevelError},
}
for _, testCase := range tc {
t.Run(testCase.Name, func(t *testing.T) {
got := scoreFactorToSARIFSeverityLevel(testCase.ScoreFactor)
want := testCase.ExpectedSARIFLevel
if got != want {
t.Errorf("got %s, want %s", got, want)
}
})
}
}

View File

@@ -32,7 +32,7 @@ func (reportMock *ReportMock) SetClusterName(clusterName string) {
}
func (reportMock *ReportMock) GetURL() string {
u := fmt.Sprintf("https://%s/account/sign-up", getter.GetKSCloudAPIConnector().GetFrontendURL())
u := fmt.Sprintf("https://%s/account/sign-up", getter.GetKSCloudAPIConnector().GetCloudUIURL())
if reportMock.query != "" {
u += fmt.Sprintf("?%s", reportMock.query)
}
@@ -44,8 +44,9 @@ func (reportMock *ReportMock) DisplayReportURL() {
sep := "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
message := sep + "\n"
message += "Scan results have not been submitted: " + reportMock.message + "\n"
message += "Sign up for free: "
message += reportMock.GetURL() + "\n"
if reportMock.query != "" {
message += "For more details: " + reportMock.query + "\n"
}
message += sep + "\n"
cautils.InfoTextDisplay(os.Stderr, fmt.Sprintf("\n%s\n", message))
}

View File

@@ -105,7 +105,7 @@ func (report *ReportEventReceiver) prepareReport(opaSessionObj *cautils.OPASessi
func (report *ReportEventReceiver) GetURL() string {
u := url.URL{}
u.Host = getter.GetKSCloudAPIConnector().GetFrontendURL()
u.Host = getter.GetKSCloudAPIConnector().GetCloudUIURL()
parseHost(&u)
report.addPathURL(&u)

View File

@@ -105,14 +105,4 @@ func TestGetURL(t *testing.T) {
)
assert.Equal(t, "https://cloud.armosec.io/account/sign-up?customerGUID=1234&invitationToken=token&utm_campaign=Submit&utm_medium=CLI&utm_source=GitHub", reporter.GetURL())
}
// Test None submit url
{
reporter := NewReportMock(NO_SUBMIT_QUERY, "")
assert.Equal(t, "https://cloud.armosec.io/account/sign-up?utm_source=GitHub&utm_medium=CLI&utm_campaign=no_submit", reporter.GetURL())
}
// Test None report url
{
reporter := NewReportMock("", "")
assert.Equal(t, "https://cloud.armosec.io/account/sign-up", reporter.GetURL())
}
}

View File

@@ -11,7 +11,7 @@ import (
func (report *ReportEventReceiver) initEventReceiverURL() {
urlObj := url.URL{}
urlObj.Host = getter.GetKSCloudAPIConnector().GetReportReceiverURL()
urlObj.Host = getter.GetKSCloudAPIConnector().GetCloudReportURL()
parseHost(&urlObj)
urlObj.Path = "/k8s/v2/postureReport"

View File

@@ -86,7 +86,7 @@ func NewPrinter(printFormat, formatVersion string, verboseMode bool, viewType ca
case "v2":
return printerv2.NewJsonPrinter()
default:
logger.L().Warning("Deprecated format version", helpers.String("run", "--format-version=v2"))
logger.L().Warning("Deprecated format version", helpers.String("run", "--format-version=v2"), helpers.String("This will not be supported after", "1/Jan/2023"))
return printerv1.NewJsonPrinter()
}
case printer.JunitResultFormat:
@@ -97,6 +97,8 @@ func NewPrinter(printFormat, formatVersion string, verboseMode bool, viewType ca
return printerv2.NewPdfPrinter()
case printer.HtmlFormat:
return printerv2.NewHtmlPrinter()
case printer.SARIFFormat:
return printerv2.NewSARIFPrinter()
default:
return printerv2.NewPrettyPrinter(verboseMode, formatVersion, viewType)
}

File diff suppressed because one or more lines are too long

BIN
docs/ks-cli-arch.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
docs/ks-operator-arch.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -64,24 +64,24 @@ But if you wish to exclude all namespaces **OR** any resource with the label `"e
Same works with the `posturePolicies` list ->
e.g. If you wish to exclude the resources declared in the `resources` list that failed when scanning the `NSA` framework **AND** failed the `Allowed hostPath` control, the `posturePolicies` list should look as follows:
e.g. If you wish to exclude the resources declared in the `resources` list that failed when scanning the `NSA` framework **AND** failed the `HostPath mount` control, the `posturePolicies` list should look as follows:
```
"posturePolicies": [
{
"frameworkName": "NSA",
"controlName": "Allowed hostPath"
"controlName": "HostPath mount"
}
]
```
But if you wish to exclude the resources declared in the `resources` list that failed when scanning the `NSA` framework **OR** failed the `Allowed hostPath` control, the `posturePolicies` list should look as follows:
But if you wish to exclude the resources declared in the `resources` list that failed when scanning the `NSA` framework **OR** failed the `HostPath mount` control, the `posturePolicies` list should look as follows:
```
"posturePolicies": [
{
"frameworkName": "NSA"
},
{
"controlName": "Allowed hostPath"
"controlName": "HostPath mount"
}
]
```
@@ -122,7 +122,7 @@ The resources
]
```
### Exclude deployments in the default namespace that failed the "Allowed hostPath" control
### Exclude deployments in the default namespace that failed the "HostPath mount" control
```
[
{
@@ -142,7 +142,7 @@ The resources
],
"posturePolicies": [
{
"controlName": "Allowed hostPath"
"controlName": "HostPath mount"
}
]
}

View File

@@ -15,7 +15,7 @@
],
"posturePolicies": [
{
"controlName": "Allowed hostPath"
"controlName": "HostPath mount"
}
]
}

View File

@@ -16,7 +16,7 @@
],
"posturePolicies": [
{
"controlName": "Allowed hostPath"
"controlName": "HostPath mount"
}
]
}

View File

@@ -98,56 +98,56 @@ kubescape_object_failed_count{framework="NSA",control="Privileged container",nam
kubescape_object_failed_count{framework="NSA",control="Privileged container",namespace="kubescape",name="armo-kubescape",groupVersionKind="batch/v1/CronJob"} 1
# Failed object from "NSA" control "Privileged container"
kubescape_object_failed_count{framework="NSA",control="Privileged container",namespace="kubescape",name="armo-scan-scheduler",groupVersionKind="batch/v1/CronJob"} 1
# Number of resources found as part of NSA control Allowed hostPath
kubescape_resources_found_count{framework="NSA",control="Allowed hostPath"} 22
# Number of resources excluded as part of NSA control Allowed hostPath
kubescape_resources_excluded_count{framework="NSA",control="Allowed hostPath"} 0
# Number of resources failed as part of NSA control Allowed hostPath
kubescape_resources_failed_count{framework="NSA",control="Allowed hostPath"} 7
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="kube-system",name="kube-proxy",groupVersionKind="apps/v1/DaemonSet"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="kube-system",name="etcd-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="kube-system",name="kube-controller-manager-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="kube-system",name="storage-provisioner",groupVersionKind="v1/Pod"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-webhook",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-websocket",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="kubescape",name="armo-web-socket",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="kubescape",name="armo-vuln-scan",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-oracle",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-posture",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-rbac",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-vuln-scan",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-audit",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-dashboard-aggregator",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-notification-server",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-ocimage",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="kube-system",name="coredns",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="nginx-ingress",name="nginx-ingress",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="kubescape",name="armo-kubescape",groupVersionKind="batch/v1/CronJob"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="kubescape",name="armo-scan-scheduler",groupVersionKind="batch/v1/CronJob"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="kube-system",name="kube-apiserver-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="kube-system",name="kube-scheduler-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Number of resources found as part of NSA control HostPath mount
kubescape_resources_found_count{framework="NSA",control="HostPath mount"} 22
# Number of resources excluded as part of NSA control HostPath mount
kubescape_resources_excluded_count{framework="NSA",control="HostPath mount"} 0
# Number of resources failed as part of NSA control HostPath mount
kubescape_resources_failed_count{framework="NSA",control="HostPath mount"} 7
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="kube-system",name="kube-proxy",groupVersionKind="apps/v1/DaemonSet"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="kube-system",name="etcd-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="kube-system",name="kube-controller-manager-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="kube-system",name="storage-provisioner",groupVersionKind="v1/Pod"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="cyberarmor-system",name="ca-webhook",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="cyberarmor-system",name="ca-websocket",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="kubescape",name="armo-web-socket",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="kubescape",name="armo-vuln-scan",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="cyberarmor-system",name="ca-oracle",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="cyberarmor-system",name="ca-posture",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="cyberarmor-system",name="ca-rbac",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="cyberarmor-system",name="ca-vuln-scan",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="cyberarmor-system",name="ca-audit",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="cyberarmor-system",name="ca-dashboard-aggregator",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="cyberarmor-system",name="ca-notification-server",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="cyberarmor-system",name="ca-ocimage",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="kube-system",name="coredns",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="nginx-ingress",name="nginx-ingress",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="kubescape",name="armo-kubescape",groupVersionKind="batch/v1/CronJob"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="kubescape",name="armo-scan-scheduler",groupVersionKind="batch/v1/CronJob"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="kube-system",name="kube-apiserver-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="kube-system",name="kube-scheduler-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Number of resources found as part of NSA control Automatic mapping of service account
kubescape_resources_found_count{framework="NSA",control="Automatic mapping of service account"} 47
# Number of resources excluded as part of NSA control Automatic mapping of service account
@@ -2668,56 +2668,56 @@ kubescape_object_failed_count{framework="ArmoBest",control="Privileged container
kubescape_object_failed_count{framework="ArmoBest",control="Privileged container",namespace="kubescape",name="armo-kubescape",groupVersionKind="batch/v1/CronJob"} 1
# Failed object from "ArmoBest" control "Privileged container"
kubescape_object_failed_count{framework="ArmoBest",control="Privileged container",namespace="kubescape",name="armo-scan-scheduler",groupVersionKind="batch/v1/CronJob"} 1
# Number of resources found as part of ArmoBest control Allowed hostPath
kubescape_resources_found_count{framework="ArmoBest",control="Allowed hostPath"} 22
# Number of resources excluded as part of ArmoBest control Allowed hostPath
kubescape_resources_excluded_count{framework="ArmoBest",control="Allowed hostPath"} 0
# Number of resources failed as part of ArmoBest control Allowed hostPath
kubescape_resources_failed_count{framework="ArmoBest",control="Allowed hostPath"} 7
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="kube-system",name="kube-proxy",groupVersionKind="apps/v1/DaemonSet"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="kube-system",name="kube-controller-manager-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="kube-system",name="storage-provisioner",groupVersionKind="v1/Pod"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="kube-system",name="etcd-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="kubescape",name="armo-web-socket",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-webhook",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-websocket",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="kube-system",name="coredns",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="nginx-ingress",name="nginx-ingress",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="kubescape",name="armo-vuln-scan",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-oracle",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-posture",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-rbac",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-vuln-scan",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-audit",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-dashboard-aggregator",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-notification-server",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-ocimage",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="kubescape",name="armo-kubescape",groupVersionKind="batch/v1/CronJob"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="kubescape",name="armo-scan-scheduler",groupVersionKind="batch/v1/CronJob"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="kube-system",name="kube-apiserver-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="kube-system",name="kube-scheduler-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Number of resources found as part of ArmoBest control HostPath mount
kubescape_resources_found_count{framework="ArmoBest",control="HostPath mount"} 22
# Number of resources excluded as part of ArmoBest control HostPath mount
kubescape_resources_excluded_count{framework="ArmoBest",control="HostPath mount"} 0
# Number of resources failed as part of ArmoBest control HostPath mount
kubescape_resources_failed_count{framework="ArmoBest",control="HostPath mount"} 7
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="kube-system",name="kube-proxy",groupVersionKind="apps/v1/DaemonSet"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="kube-system",name="kube-controller-manager-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="kube-system",name="storage-provisioner",groupVersionKind="v1/Pod"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="kube-system",name="etcd-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="kubescape",name="armo-web-socket",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="cyberarmor-system",name="ca-webhook",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="cyberarmor-system",name="ca-websocket",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="kube-system",name="coredns",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="nginx-ingress",name="nginx-ingress",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="kubescape",name="armo-vuln-scan",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="cyberarmor-system",name="ca-oracle",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="cyberarmor-system",name="ca-posture",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="cyberarmor-system",name="ca-rbac",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="cyberarmor-system",name="ca-vuln-scan",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="cyberarmor-system",name="ca-audit",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="cyberarmor-system",name="ca-dashboard-aggregator",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="cyberarmor-system",name="ca-notification-server",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="cyberarmor-system",name="ca-ocimage",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="kubescape",name="armo-kubescape",groupVersionKind="batch/v1/CronJob"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="kubescape",name="armo-scan-scheduler",groupVersionKind="batch/v1/CronJob"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="kube-system",name="kube-apiserver-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="kube-system",name="kube-scheduler-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Number of resources found as part of ArmoBest control Automatic mapping of service account
kubescape_resources_found_count{framework="ArmoBest",control="Automatic mapping of service account"} 47
# Number of resources excluded as part of ArmoBest control Automatic mapping of service account

View File

@@ -54,26 +54,26 @@ kubescape_resources_excluded_count{framework="NSA",control="Privileged container
kubescape_resources_failed_count{framework="NSA",control="Privileged container"} 1
# Failed object from "NSA" control "Privileged container"
kubescape_object_failed_count{framework="NSA",control="Privileged container",namespace="kube-system",name="kube-proxy",groupVersionKind="apps/v1/DaemonSet"} 1
# Number of resources found as part of NSA control Allowed hostPath
kubescape_resources_found_count{framework="NSA",control="Allowed hostPath"} 22
# Number of resources excluded as part of NSA control Allowed hostPath
kubescape_resources_excluded_count{framework="NSA",control="Allowed hostPath"} 0
# Number of resources failed as part of NSA control Allowed hostPath
kubescape_resources_failed_count{framework="NSA",control="Allowed hostPath"} 7
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="kube-system",name="etcd-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="kube-system",name="kube-controller-manager-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="kube-system",name="storage-provisioner",groupVersionKind="v1/Pod"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="kubescape",name="armo-web-socket",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-websocket",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-webhook",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "Allowed hostPath"
kubescape_object_failed_count{framework="NSA",control="Allowed hostPath",namespace="kube-system",name="kube-proxy",groupVersionKind="apps/v1/DaemonSet"} 1
# Number of resources found as part of NSA control HostPath mount
kubescape_resources_found_count{framework="NSA",control="HostPath mount"} 22
# Number of resources excluded as part of NSA control HostPath mount
kubescape_resources_excluded_count{framework="NSA",control="HostPath mount"} 0
# Number of resources failed as part of NSA control HostPath mount
kubescape_resources_failed_count{framework="NSA",control="HostPath mount"} 7
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="kube-system",name="etcd-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="kube-system",name="kube-controller-manager-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="kube-system",name="storage-provisioner",groupVersionKind="v1/Pod"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="kubescape",name="armo-web-socket",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="cyberarmor-system",name="ca-websocket",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="cyberarmor-system",name="ca-webhook",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "NSA" control "HostPath mount"
kubescape_object_failed_count{framework="NSA",control="HostPath mount",namespace="kube-system",name="kube-proxy",groupVersionKind="apps/v1/DaemonSet"} 1
# Number of resources found as part of NSA control Automatic mapping of service account
kubescape_resources_found_count{framework="NSA",control="Automatic mapping of service account"} 47
# Number of resources excluded as part of NSA control Automatic mapping of service account
@@ -872,26 +872,26 @@ kubescape_resources_excluded_count{framework="ArmoBest",control="Privileged cont
kubescape_resources_failed_count{framework="ArmoBest",control="Privileged container"} 1
# Failed object from "ArmoBest" control "Privileged container"
kubescape_object_failed_count{framework="ArmoBest",control="Privileged container",namespace="kube-system",name="kube-proxy",groupVersionKind="apps/v1/DaemonSet"} 1
# Number of resources found as part of ArmoBest control Allowed hostPath
kubescape_resources_found_count{framework="ArmoBest",control="Allowed hostPath"} 22
# Number of resources excluded as part of ArmoBest control Allowed hostPath
kubescape_resources_excluded_count{framework="ArmoBest",control="Allowed hostPath"} 0
# Number of resources failed as part of ArmoBest control Allowed hostPath
kubescape_resources_failed_count{framework="ArmoBest",control="Allowed hostPath"} 7
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="kube-system",name="kube-proxy",groupVersionKind="apps/v1/DaemonSet"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="kube-system",name="etcd-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="kube-system",name="kube-controller-manager-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="kube-system",name="storage-provisioner",groupVersionKind="v1/Pod"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="kubescape",name="armo-web-socket",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-webhook",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "Allowed hostPath"
kubescape_object_failed_count{framework="ArmoBest",control="Allowed hostPath",namespace="cyberarmor-system",name="ca-websocket",groupVersionKind="apps/v1/Deployment"} 1
# Number of resources found as part of ArmoBest control HostPath mount
kubescape_resources_found_count{framework="ArmoBest",control="HostPath mount"} 22
# Number of resources excluded as part of ArmoBest control HostPath mount
kubescape_resources_excluded_count{framework="ArmoBest",control="HostPath mount"} 0
# Number of resources failed as part of ArmoBest control HostPath mount
kubescape_resources_failed_count{framework="ArmoBest",control="HostPath mount"} 7
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="kube-system",name="kube-proxy",groupVersionKind="apps/v1/DaemonSet"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="kube-system",name="etcd-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="kube-system",name="kube-controller-manager-david-virtualbox",groupVersionKind="v1/Pod"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="kube-system",name="storage-provisioner",groupVersionKind="v1/Pod"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="kubescape",name="armo-web-socket",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="cyberarmor-system",name="ca-webhook",groupVersionKind="apps/v1/Deployment"} 1
# Failed object from "ArmoBest" control "HostPath mount"
kubescape_object_failed_count{framework="ArmoBest",control="HostPath mount",namespace="cyberarmor-system",name="ca-websocket",groupVersionKind="apps/v1/Deployment"} 1
# Number of resources found as part of ArmoBest control Automatic mapping of service account
kubescape_resources_found_count{framework="ArmoBest",control="Automatic mapping of service account"} 47
# Number of resources excluded as part of ArmoBest control Automatic mapping of service account

72
go.mod
View File

@@ -3,7 +3,8 @@ module github.com/kubescape/kubescape/v2
go 1.18
require (
github.com/armosec/armoapi-go v0.0.115
cloud.google.com/go/containeranalysis v0.4.0
github.com/armosec/armoapi-go v0.0.119
github.com/armosec/go-git-url v0.0.15
github.com/armosec/utils-go v0.0.12
github.com/armosec/utils-k8s-go v0.0.12
@@ -15,35 +16,44 @@ require (
github.com/google/uuid v1.3.0
github.com/johnfercher/maroto v0.37.0
github.com/kubescape/go-logger v0.0.6
github.com/kubescape/k8s-interface v0.0.83
github.com/kubescape/opa-utils v0.0.194
github.com/kubescape/rbac-utils v0.0.17
github.com/kubescape/k8s-interface v0.0.89
github.com/kubescape/opa-utils v0.0.200
github.com/kubescape/rbac-utils v0.0.19
github.com/libgit2/git2go/v33 v33.0.9
github.com/mattn/go-isatty v0.0.14
github.com/mikefarah/yq/v4 v4.29.1
github.com/olekukonko/tablewriter v0.0.5
github.com/open-policy-agent/opa v0.42.1
github.com/spf13/cobra v1.5.0
github.com/open-policy-agent/opa v0.45.0
github.com/owenrumney/go-sarif/v2 v2.1.2
github.com/spf13/cobra v1.6.1
github.com/stretchr/testify v1.8.0
github.com/whilp/git-urls v1.0.0
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3
gopkg.in/yaml.v2 v2.4.0
google.golang.org/api v0.85.0
google.golang.org/genproto v0.0.0-20220708155623-50e5f4832e73
google.golang.org/protobuf v1.28.1
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473
gopkg.in/yaml.v3 v3.0.1
helm.sh/helm/v3 v3.9.0
k8s.io/api v0.24.3
k8s.io/apimachinery v0.24.3
k8s.io/client-go v0.24.3
k8s.io/utils v0.0.0-20220706174534-f6158b442e7c
k8s.io/api v0.25.3
k8s.io/apimachinery v0.25.3
k8s.io/client-go v0.25.3
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed
sigs.k8s.io/kustomize/api v0.11.4
sigs.k8s.io/kustomize/kyaml v0.13.6
sigs.k8s.io/yaml v1.3.0
)
require github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
require (
cloud.google.com/go/compute v1.7.0 // indirect
cloud.google.com/go/container v1.2.0 // indirect
cloud.google.com/go/grafeas v0.2.0 // indirect
github.com/Azure/azure-sdk-for-go v66.0.0+incompatible // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.24 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.18 // 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/azure/auth v0.5.11 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
@@ -60,8 +70,10 @@ require (
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/a8m/envsubst v1.3.0 // indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/agnivade/levenshtein v1.0.1 // indirect
github.com/agnivade/levenshtein v1.1.1 // indirect
github.com/alecthomas/participle/v2 v2.0.0-beta.5 // indirect
github.com/aws/aws-sdk-go v1.44.51 // indirect
github.com/aws/aws-sdk-go-v2 v1.16.7 // indirect
github.com/aws/aws-sdk-go-v2/config v1.15.13 // indirect
@@ -83,7 +95,8 @@ require (
github.com/docker/docker v20.10.17+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/emicklei/go-restful v2.9.5+incompatible // indirect
github.com/elliotchance/orderedmap v1.5.0 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
github.com/emirpasic/gods v1.12.0 // indirect
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
github.com/ghodss/yaml v1.0.0 // indirect
@@ -96,6 +109,8 @@ require (
github.com/go-openapi/jsonreference v0.19.5 // indirect
github.com/go-openapi/swag v0.19.14 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/goccy/go-json v0.9.11 // indirect
github.com/goccy/go-yaml v1.9.6 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
@@ -103,18 +118,19 @@ require (
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/go-cmp v0.5.8 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa // indirect
github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect
github.com/googleapis/gax-go/v2 v2.4.0 // indirect
github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/inconshreveable/mousetrap v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jinzhu/copier v0.3.5 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/jung-kurt/gofpdf v1.16.2 // indirect
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
@@ -137,7 +153,7 @@ require (
github.com/shopspring/decimal v1.2.0 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/vektah/gqlparser/v2 v2.4.5 // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
github.com/xanzy/ssh-agent v0.3.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
@@ -150,28 +166,26 @@ require (
go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.22.0 // indirect
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
golang.org/x/net v0.0.0-20220909164309-bea034e7d591 // indirect
golang.org/x/oauth2 v0.0.0-20220630143837-2104d58473e0 // indirect
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
gonum.org/v1/gonum v0.9.1 // indirect
google.golang.org/api v0.84.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220708155623-50e5f4832e73 // indirect
google.golang.org/grpc v1.47.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
google.golang.org/grpc v1.49.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
k8s.io/apiextensions-apiserver v0.24.2 // indirect
k8s.io/klog/v2 v2.60.1 // indirect
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 // indirect
k8s.io/klog/v2 v2.70.1 // indirect
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect
sigs.k8s.io/controller-runtime v0.12.3 // indirect
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
)
replace github.com/libgit2/git2go/v33 => ./git2go

752
go.sum

File diff suppressed because it is too large Load Diff

View File

@@ -55,7 +55,7 @@ When scanning is in progress
}
```
### Check scanning progress status
Check the scanning status - is the scanning in progress or done? This is meant for a waiting mechanize since the API does not return the entire results object when the scanning is done
Check the scanning status - is the scanning in progress or done. This is meant for a waiting mechanize since the API does not return the entire results object when the scanning is done
* GET `/v1/status` - Request kubescape scan status
* * query `id=<string>` -> Check status of a specific scan. If empty, it will check if any scan is still in progress
@@ -101,7 +101,6 @@ When scanning is not in progress
"excludedNamespaces": [<str>], // list of namespaces to exclude (same as 'kubescape scan --excluded-namespaces')
"includeNamespaces": [<str>], // list of namespaces to include (same as 'kubescape scan --include-namespaces')
"useCachedArtifacts"`: <bool>, // use the cached artifacts instead of downloading (offline support)
"submit": <bool>, // submit results to Kubescape cloud (same as 'kubescape scan --submit')
"hostScanner": <bool>, // deploy Kubescape K8s host-scanner DaemonSet in the scanned cluster (same as 'kubescape scan --enable-host-scan')
"keepLocal": <bool>, // do not submit results to Kubescape cloud (same as 'kubescape scan --keep-local')
"account": <str>, // account ID (same as 'kubescape scan --account')
@@ -132,7 +131,7 @@ When scanning is not in progress
1. Trigger kubescape scan
```bash
curl --header "Content-Type: application/json" --request POST --data '{"hostScanner":true, "submit": true}' http://127.0.0.1:8080/v1/scan
curl --header "Content-Type: application/json" --request POST --data '{"hostScanner":true}' http://127.0.0.1:8080/v1/scan
```
2. Get kubescape scan results
@@ -143,13 +142,13 @@ When scanning is not in progress
#### Trigger scan and wait for the scan to end
```bash
curl --header "Content-Type: application/json" --request POST --data '{"hostScanner":true, "submit": true}' http://127.0.0.1:8080/v1/scan?wait -o scan_results.json
curl --header "Content-Type: application/json" --request POST --data '{"hostScanner":true}' http://127.0.0.1:8080/v1/scan?wait -o scan_results.json
```
#### Scan single namespace with a specific framework
```bash
curl --header "Content-Type: application/json" \
--request POST \
--data '{"hostScanner":true, "submit":true, "includeNamespaces": ["kubescape"], "targetType": "framework", "targetNames": ["nsa"] }' \
--data '{"hostScanner":true, "includeNamespaces": ["kubescape"], "targetType": "framework", "targetNames": ["nsa"] }' \
http://127.0.0.1:8080/v1/scan
```
@@ -171,7 +170,6 @@ go tool pprof http://localhost:6060/debug/pprof/heap
## Supported environment variables
* `KS_ACCOUNT`: Account ID
* `KS_SUBMIT`: Submit the results to the Kubescape SaaS version
* `KS_EXCLUDE_NAMESPACES`: List of namespaces to exclude, e.g. `KS_EXCLUDE_NAMESPACES=kube-system,kube-public`
* `KS_INCLUDE_NAMESPACES`: List of namespaces to include, rest of the namespaces will be ignored. e.g. `KS_INCLUDE_NAMESPACES=dev,prod`
* `KS_HOST_SCAN_YAML`: Full path to the host scanner YAML

View File

@@ -6,60 +6,63 @@ import subprocess
BASE_GETTER_CONST = "github.com/kubescape/kubescape/v2/core/cautils/getter"
def checkStatus(status, msg):
def check_status(status, msg):
if status != 0:
sys.stderr.write(msg)
exit(status)
def getBuildDir():
currentPlatform = platform.system()
buildDir = "build/"
def get_build_dir():
current_platform = platform.system()
build_dir = ""
if currentPlatform == "Windows": return os.path.join(buildDir, "windows-latest")
if currentPlatform == "Linux": return os.path.join(buildDir, "ubuntu-latest")
if currentPlatform == "Darwin": return os.path.join(buildDir, "macos-latest")
raise OSError("Platform %s is not supported!" % (currentPlatform))
if current_platform == "Windows": build_dir = "windows-latest"
elif current_platform == "Linux": build_dir = "ubuntu-latest"
elif current_platform == "Darwin": build_dir = "macos-latest"
else: raise OSError("Platform %s is not supported!" % (current_platform))
def getPackageName():
packageName = "kubescape"
# if platform.system() == "Windows": packageName += ".exe"
return os.path.join("build", build_dir)
return packageName
def get_package_name():
package_name = "kubescape"
# TODO: if platform.system() == "Windows": packageName += ".exe" - we should find all places were we access the windows executable before changing the extension
return package_name
def main():
print("Building Kubescape")
# print environment variables
# print(os.environ)
# Set some variables
packageName = getPackageName()
buildUrl = "github.com/kubescape/kubescape/v2/core/cautils.BuildNumber"
releaseVersion = os.getenv("RELEASE")
package_name = get_package_name()
build_url = "github.com/kubescape/kubescape/v2/core/cautils.BuildNumber"
release_version = os.getenv("RELEASE")
client_var = "github.com/kubescape/kubescape/v2/core/cautils.Client"
client_name = os.getenv("CLIENT")
# Create build directory
buildDir = getBuildDir()
build_dir = get_build_dir()
ks_file = os.path.join(buildDir, packageName)
ks_file = os.path.join(build_dir, package_name)
hash_file = ks_file + ".sha256"
if not os.path.isdir(buildDir):
os.makedirs(buildDir)
if not os.path.isdir(build_dir):
os.makedirs(build_dir)
# Build kubescape
ldflags = "-w -s"
if releaseVersion:
ldflags += " -X {}={}".format(buildUrl, releaseVersion)
build_command = ["go", "build", "-tags=static", "-o", ks_file, "-ldflags" ,ldflags]
if release_version:
ldflags += " -X {}={}".format(build_url, release_version)
if client_name:
ldflags += " -X {}={}".format(client_var, client_name)
build_command = ["go", "build", "-buildmode=pie", "-tags=static", "-o", ks_file, "-ldflags" ,ldflags]
print("Building kubescape and saving here: {}".format(ks_file))
print("Build command: {}".format(" ".join(build_command)))
status = subprocess.call(build_command)
checkStatus(status, "Failed to build kubescape")
check_status(status, "Failed to build kubescape")
sha256 = hashlib.sha256()
with open(ks_file, "rb") as kube:

View File

@@ -10,7 +10,7 @@
```bash
curl --header "Content-Type: application/json" \
--request POST \
--data '{"account":"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX","hostScanner":true, "submit":true}' \
--data '{"account":"XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX","hostScanner":true}' \
http://127.0.0.1:8080/v1/scan
```

View File

@@ -12,18 +12,20 @@ require (
github.com/gorilla/schema v1.2.0
github.com/kubescape/go-logger v0.0.6
github.com/kubescape/kubescape/v2 v2.0.0-00010101000000-000000000000
github.com/kubescape/opa-utils v0.0.194
github.com/kubescape/opa-utils v0.0.200
github.com/stretchr/testify v1.8.0
k8s.io/utils v0.0.0-20220706174534-f6158b442e7c
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed
)
require (
cloud.google.com/go/compute v1.7.0 // indirect
cloud.google.com/go/container v1.2.0 // indirect
cloud.google.com/go/containeranalysis v0.4.0 // indirect
cloud.google.com/go/grafeas v0.2.0 // indirect
github.com/Azure/azure-sdk-for-go v66.0.0+incompatible // indirect
github.com/Azure/go-autorest v14.2.0+incompatible // indirect
github.com/Azure/go-autorest/autorest v0.11.24 // indirect
github.com/Azure/go-autorest/autorest/adal v0.9.18 // 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/azure/auth v0.5.11 // indirect
github.com/Azure/go-autorest/autorest/azure/cli v0.4.5 // indirect
github.com/Azure/go-autorest/autorest/date v0.3.0 // indirect
@@ -40,9 +42,11 @@ require (
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/a8m/envsubst v1.3.0 // indirect
github.com/acomagu/bufpipe v1.0.3 // indirect
github.com/agnivade/levenshtein v1.0.1 // indirect
github.com/armosec/armoapi-go v0.0.115 // indirect
github.com/agnivade/levenshtein v1.1.1 // indirect
github.com/alecthomas/participle/v2 v2.0.0-beta.5 // indirect
github.com/armosec/armoapi-go v0.0.119 // indirect
github.com/armosec/go-git-url v0.0.15 // indirect
github.com/armosec/utils-k8s-go v0.0.12 // indirect
github.com/asaskevich/govalidator v0.0.0-20210307081110-f21760c49a8d // indirect
@@ -68,7 +72,8 @@ require (
github.com/docker/docker v20.10.17+incompatible // indirect
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/emicklei/go-restful v2.9.5+incompatible // indirect
github.com/elliotchance/orderedmap v1.5.0 // indirect
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
github.com/emirpasic/gods v1.12.0 // indirect
github.com/enescakir/emoji v1.0.0 // indirect
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
@@ -92,6 +97,8 @@ require (
github.com/go-openapi/validate v0.21.0 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/goccy/go-json v0.9.11 // indirect
github.com/goccy/go-yaml v1.9.6 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.2.0 // indirect
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
@@ -100,24 +107,27 @@ require (
github.com/google/go-cmp v0.5.8 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.0.0-20220520183353-fd19c99a87aa // indirect
github.com/googleapis/enterprise-certificate-proxy v0.1.0 // indirect
github.com/googleapis/gax-go/v2 v2.4.0 // indirect
github.com/huandu/xstrings v1.3.2 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
github.com/jinzhu/copier v0.3.5 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/johnfercher/maroto v0.37.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/jung-kurt/gofpdf v1.16.2 // indirect
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351 // indirect
github.com/kubescape/k8s-interface v0.0.83 // indirect
github.com/kubescape/rbac-utils v0.0.17 // indirect
github.com/kubescape/k8s-interface v0.0.89 // indirect
github.com/kubescape/rbac-utils v0.0.19 // indirect
github.com/libgit2/git2go/v33 v33.0.9 // indirect
github.com/magiconair/properties v1.8.6 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-runewidth v0.0.9 // indirect
github.com/mikefarah/yq/v4 v4.29.1 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
@@ -128,9 +138,10 @@ require (
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/oklog/ulid v1.3.1 // indirect
github.com/olekukonko/tablewriter v0.0.5 // indirect
github.com/open-policy-agent/opa v0.42.1 // indirect
github.com/open-policy-agent/opa v0.45.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
github.com/owenrumney/go-sarif/v2 v2.1.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/pquerna/cachecontrol v0.1.0 // indirect
@@ -140,7 +151,7 @@ require (
github.com/shopspring/decimal v1.2.0 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/vektah/gqlparser/v2 v2.4.5 // indirect
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
github.com/whilp/git-urls v1.0.0 // indirect
github.com/xanzy/ssh-agent v0.3.0 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
@@ -156,35 +167,37 @@ require (
go.uber.org/zap v1.22.0 // indirect
golang.org/x/crypto v0.0.0-20220525230936-793ad666bf5e // indirect
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
golang.org/x/net v0.0.0-20220909164309-bea034e7d591 // indirect
golang.org/x/oauth2 v0.0.0-20220630143837-2104d58473e0 // indirect
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
golang.org/x/xerrors v0.0.0-20220609144429-65e65417b02f // indirect
gonum.org/v1/gonum v0.9.1 // indirect
google.golang.org/api v0.84.0 // indirect
google.golang.org/api v0.85.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/genproto v0.0.0-20220708155623-50e5f4832e73 // indirect
google.golang.org/grpc v1.47.0 // indirect
google.golang.org/protobuf v1.28.0 // indirect
google.golang.org/grpc v1.49.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/op/go-logging.v1 v1.0.0-20160211212156-b2cb9fa56473 // indirect
gopkg.in/square/go-jose.v2 v2.6.0 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
helm.sh/helm/v3 v3.9.0 // indirect
k8s.io/api v0.24.3 // indirect
k8s.io/api v0.25.3 // indirect
k8s.io/apiextensions-apiserver v0.24.2 // indirect
k8s.io/apimachinery v0.24.3 // indirect
k8s.io/client-go v0.24.3 // indirect
k8s.io/klog/v2 v2.60.1 // indirect
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 // indirect
k8s.io/apimachinery v0.25.3 // indirect
k8s.io/client-go v0.25.3 // indirect
k8s.io/klog/v2 v2.70.1 // indirect
k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect
sigs.k8s.io/controller-runtime v0.12.3 // indirect
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/kustomize/api v0.11.4 // indirect
sigs.k8s.io/kustomize/kyaml v0.13.6 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@ package v1
import (
"encoding/json"
"fmt"
"io/ioutil"
"io"
"net/http"
"sync"
@@ -124,7 +124,7 @@ func getScanParamsFromRequest(r *http.Request, scanID string) (*scanRequestParam
return scanRequestParams, fmt.Errorf("failed to parse query params, reason: %s", err.Error())
}
readBuffer, err := ioutil.ReadAll(r.Body)
readBuffer, err := io.ReadAll(r.Body)
if err != nil {
// handler.writeError(w, fmt.Errorf("failed to read request body, reason: %s", err.Error()), scanID)
return scanRequestParams, fmt.Errorf("failed to read request body, reason: %s", err.Error())

View File

@@ -66,6 +66,6 @@ echo -e "\033[0m"
$KUBESCAPE_EXEC version
echo
echo -e "\033[35mUsage: $ $KUBESCAPE_EXEC scan --submit --enable-host-scan --verbose"
echo -e "\033[35mUsage: $ $KUBESCAPE_EXEC scan --enable-host-scan --verbose"
echo -e "\033[0m"

View File

@@ -3,10 +3,12 @@ package main
import (
logger "github.com/kubescape/go-logger"
"github.com/kubescape/kubescape/v2/cmd"
)
func main() {
if err := cmd.Execute(); err != nil {
logger.L().Fatal(err.Error())
}
}

View File

@@ -22,7 +22,6 @@ def run(kubescape_exec:str):
test_command(command=[kubescape_exec, "scan", "framework"])
test_command(command=[kubescape_exec, "scan", "control"])
test_command(command=[kubescape_exec, "submit", "results"])
test_command(command=[kubescape_exec, "submit", "rbac"])
print("Done testing commands")

View File

@@ -13,15 +13,15 @@ def scan_all(kubescape_exec: str):
def scan_control_name(kubescape_exec: str):
return smoke_utils.run_command(command=[kubescape_exec, "scan", "control", 'Allowed hostPath', all_files, "--enable-host-scan=false"])
return smoke_utils.run_command(command=[kubescape_exec, "scan", "control", 'HostPath mount', all_files, "--enable-host-scan=false"])
def scan_control_id(kubescape_exec: str):
return smoke_utils.run_command(command=[kubescape_exec, "scan", "control", 'C-0006', all_files, "--enable-host-scan=false"])
return smoke_utils.run_command(command=[kubescape_exec, "scan", "control", 'C-0048', all_files, "--enable-host-scan=false"])
def scan_controls(kubescape_exec: str):
return smoke_utils.run_command(command=[kubescape_exec, "scan", "control", 'Allowed hostPath,Allow privilege escalation', all_files, "--enable-host-scan=false"])
return smoke_utils.run_command(command=[kubescape_exec, "scan", "control", 'HostPath mount,Allow privilege escalation', all_files, "--enable-host-scan=false"])
def scan_framework(kubescape_exec: str):