mirror of
https://github.com/kubescape/kubescape.git
synced 2026-03-03 02:00:27 +00:00
Compare commits
104 Commits
v3.0.12-rc
...
v3.0.23-rc
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
985d72e5fb | ||
|
|
70a9380966 | ||
|
|
f706d126f5 | ||
|
|
600f19406e | ||
|
|
d7ebf3239b | ||
|
|
5e0b25b04a | ||
|
|
98fe2347fa | ||
|
|
9b22d3284e | ||
|
|
9544e9cd66 | ||
|
|
1ed1bb11f2 | ||
|
|
b8ca1fcbce | ||
|
|
326a3e4c63 | ||
|
|
b348acd291 | ||
|
|
4fc3eacf7b | ||
|
|
d6030a9c03 | ||
|
|
e87bf7b723 | ||
|
|
4ef0b27ccf | ||
|
|
219582b92a | ||
|
|
07ed8c61f1 | ||
|
|
c585abc21a | ||
|
|
08696c583a | ||
|
|
7d94dc74bb | ||
|
|
570369a66f | ||
|
|
97f24920e8 | ||
|
|
f57305280f | ||
|
|
53c134cbc3 | ||
|
|
3c3a1838e3 | ||
|
|
adfd09a9d4 | ||
|
|
43ac47ec51 | ||
|
|
ec715ab68b | ||
|
|
fbff5873f7 | ||
|
|
a81eab0a1a | ||
|
|
cfc52856b3 | ||
|
|
5707d7f7e4 | ||
|
|
4f3ef49f99 | ||
|
|
a9ac880356 | ||
|
|
761d4c6ff4 | ||
|
|
bbb2aafc7e | ||
|
|
7735087937 | ||
|
|
5b9c6491de | ||
|
|
b0e3744140 | ||
|
|
0451cdb345 | ||
|
|
4546465f4a | ||
|
|
52c564b2a4 | ||
|
|
0abc81003e | ||
|
|
817d4902ff | ||
|
|
5553a1adf0 | ||
|
|
e95352d31e | ||
|
|
5655051a95 | ||
|
|
90c359533f | ||
|
|
7013d83aa8 | ||
|
|
c4935671fe | ||
|
|
e67ef1c54d | ||
|
|
5d6b9a5e83 | ||
|
|
a6752a5a6d | ||
|
|
6f47f8dae0 | ||
|
|
d82e8daa25 | ||
|
|
1cad446fe6 | ||
|
|
12c6f34fe7 | ||
|
|
79c2dd9a2b | ||
|
|
f64d5a03af | ||
|
|
e27d1581f1 | ||
|
|
99985e3235 | ||
|
|
27782afeac | ||
|
|
0e846b2dc5 | ||
|
|
45fb0f207e | ||
|
|
b7c91c238d | ||
|
|
76635a0705 | ||
|
|
c91d69e7fd | ||
|
|
5fd7096d67 | ||
|
|
f4189cb5ec | ||
|
|
278ca5b8ae | ||
|
|
729efcb8c3 | ||
|
|
406031d4e9 | ||
|
|
9e1d0d2cd6 | ||
|
|
f3e78f9408 | ||
|
|
eea4cc0b49 | ||
|
|
1127f44c10 | ||
|
|
377509fab8 | ||
|
|
c21e2f3147 | ||
|
|
0b4c5db939 | ||
|
|
6d490fc501 | ||
|
|
dbb71ba066 | ||
|
|
d5b8532e40 | ||
|
|
db396b26f8 | ||
|
|
1242259331 | ||
|
|
ad0e50898a | ||
|
|
3cf45cffd8 | ||
|
|
ac0d982531 | ||
|
|
99e22efe7b | ||
|
|
aedeb8f9cb | ||
|
|
824e76200e | ||
|
|
8342f96a62 | ||
|
|
b824d52345 | ||
|
|
11b6567db4 | ||
|
|
c7d3105ca5 | ||
|
|
f1c15cd2b5 | ||
|
|
7507f58306 | ||
|
|
48ad56a2ef | ||
|
|
2fdec20b28 | ||
|
|
2d77ea7b62 | ||
|
|
eacd559c34 | ||
|
|
c56e5799d7 | ||
|
|
a423b41e68 |
24
.github/workflows/02-release.yaml
vendored
24
.github/workflows/02-release.yaml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
retag:
|
||||
outputs:
|
||||
NEW_TAG: ${{ steps.tag-calculator.outputs.NEW_TAG }}
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu22-core4-mem16-ssd150
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- id: tag-calculator
|
||||
@@ -89,4 +89,24 @@ jobs:
|
||||
support_platforms: true
|
||||
cosign: true
|
||||
secrets: inherit
|
||||
|
||||
post-release:
|
||||
permissions:
|
||||
actions: read
|
||||
checks: read
|
||||
deployments: read
|
||||
discussions: read
|
||||
id-token: write
|
||||
issues: read
|
||||
packages: write
|
||||
pages: read
|
||||
pull-requests: read
|
||||
repository-projects: read
|
||||
security-events: read
|
||||
statuses: read
|
||||
attestations: read
|
||||
contents: write
|
||||
uses: ./.github/workflows/e-post-release.yaml
|
||||
needs: [publish-image]
|
||||
with:
|
||||
TAG: ${{ needs.retag.outputs.NEW_TAG }}
|
||||
secrets: inherit
|
||||
|
||||
17
.github/workflows/04-publish-krew-plugin.yaml
vendored
17
.github/workflows/04-publish-krew-plugin.yaml
vendored
@@ -1,17 +0,0 @@
|
||||
name: 04-publish_krew_plugin
|
||||
permissions: read-all
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+'
|
||||
jobs:
|
||||
publish_krew_plugin:
|
||||
name: Publish Krew plugin
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository_owner == 'kubescape'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Update new version in krew-index
|
||||
uses: rajatjindal/krew-release-bot@92da038bbf995803124a8e50ebd438b2f37bbbb0 # ratchet:rajatjindal/krew-release-bot@v0.0.43
|
||||
4
.github/workflows/a-pr-scanner.yaml
vendored
4
.github/workflows/a-pr-scanner.yaml
vendored
@@ -27,7 +27,7 @@ jobs:
|
||||
name: Create cross-platform build
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu22-core4-mem16-ssd150
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
@@ -84,7 +84,7 @@ jobs:
|
||||
GITGUARDIAN_API_KEY: ${{ secrets.GITGUARDIAN_API_KEY }}
|
||||
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
|
||||
name: PR Scanner
|
||||
runs-on: ubuntu-latest
|
||||
runs-on: ubuntu22-core4-mem16-ssd150
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
|
||||
@@ -18,7 +18,7 @@ on:
|
||||
GO_VERSION:
|
||||
required: false
|
||||
type: string
|
||||
default: "1.22"
|
||||
default: "1.23"
|
||||
GO111MODULE:
|
||||
required: false
|
||||
type: string
|
||||
@@ -70,7 +70,7 @@ on:
|
||||
type: string
|
||||
GO_VERSION:
|
||||
type: string
|
||||
default: "1.22"
|
||||
default: "1.23"
|
||||
GO111MODULE:
|
||||
required: true
|
||||
type: string
|
||||
@@ -146,7 +146,7 @@ jobs:
|
||||
needs: wf-preparation
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
runs-on: ubuntu-22.04-large
|
||||
runs-on: ubuntu-large
|
||||
steps:
|
||||
- name: (debug) Step 1 - Check disk space before checkout
|
||||
run: df -h
|
||||
@@ -249,7 +249,7 @@ jobs:
|
||||
CGO_ENABLED: 0
|
||||
GO111MODULE: "on"
|
||||
BUILD_PLATFORM: linux/amd64,linux/arm64
|
||||
GO_VERSION: "1.22"
|
||||
GO_VERSION: "1.23"
|
||||
REQUIRED_TESTS: '[
|
||||
"ks_microservice_create_2_cronjob_mitre_and_nsa_proxy",
|
||||
"ks_microservice_triggering_with_cron_job",
|
||||
|
||||
@@ -1,21 +1,25 @@
|
||||
name: 03-post_release
|
||||
name: e-post_release
|
||||
permissions: read-all
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
branches:
|
||||
- 'master'
|
||||
- 'main'
|
||||
workflow_call:
|
||||
inputs:
|
||||
TAG:
|
||||
description: 'Tag name'
|
||||
required: true
|
||||
type: string
|
||||
jobs:
|
||||
post_release:
|
||||
name: Post release jobs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Digest
|
||||
uses: MCJack123/ghaction-generate-release-hashes@c03f3111b39432dde3edebe401c5a8d1ffbbf917 # ratchet:MCJack123/ghaction-generate-release-hashes@v1
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
hash-type: sha1
|
||||
file-name: kubescape-release-digests
|
||||
submodules: recursive
|
||||
- name: Update new version in krew-index
|
||||
uses: rajatjindal/krew-release-bot@v0.0.47
|
||||
if: github.repository_owner == 'kubescape'
|
||||
env:
|
||||
GITHUB_REF: ${{ inputs.TAG }}
|
||||
- name: Invoke workflow to update packaging
|
||||
uses: benc-uk/workflow-dispatch@v1
|
||||
if: github.repository_owner == 'kubescape'
|
||||
23
ADOPTERS.md
23
ADOPTERS.md
@@ -1,24 +1,5 @@
|
||||
# Adopters
|
||||
|
||||
# Well-known companies
|
||||
The Kubescape project manages this document in the central project repository.
|
||||
|
||||
List of well-known companies who are publicly acknowledge using and/or contributing to Kubescape are (in alphabetical order):
|
||||
* AWS uses Kubescape in the security training material [link](https://catalog.workshops.aws/containersecurity/en-US/module2)
|
||||
* Energi Danmark: Publicly talking about how they use Kubescape in their CI/CD pipeline [link](https://www.armosec.io/energi-danmark-business-support/)
|
||||
* Gitpod: Used Kubescape in their SOC2 compliance process [link](https://www.armosec.io/gitpod/)
|
||||
* Intel: using Kubescape for security prioritization [video](https://youtu.be/1iCW1KboypY?si=OjmnshWbpFNVPGJT)
|
||||
* Orange Business: talking about Kubescape/ARMO service they are doing [video](https://www.youtube.com/watch?v=cbJYCUM8578)
|
||||
* Rabobank: talked at KCD Amsterdam about having Kubescape in their technology stack [video](https://youtu.be/oa_YJmjwepI?si=vSrFW6seMKHj2Lze) [image](/docs/img/kcd-amsterdam-rabo.jpg)
|
||||
* VMWare/Bitnami: listing Kubescape in their public image/helm repository [link](https://github.com/bitnami/containers/tree/main/bitnami/kubescape)
|
||||
|
||||
|
||||
# Users
|
||||
|
||||
If you want to be listed here and share with others your experience, open a PR and add the bellow table:
|
||||
|
||||
|
||||
| Name | Company | Use case | Contact for questions (optional) |
|
||||
| ---- | ------- | -------- | -------------------------------- |
|
||||
| Yonathan Amzallag | ARMO | Vulnerability monitoring | yonatana@armosec.io |
|
||||
| Engin Diri | Schwarz IT (SIT) | Ensure continuous compliance for edge k8s cluster | engin.diri@mail.schwarz |
|
||||
| Idan Bidani | Cox Communications | Security analysis for k8s best practices in CI pipelines of 3,000 applications 🔒☸ | idan.bidani@cox.com |
|
||||
Go to the [centralized ADOPTERS.md](https://github.com/kubescape/project-governance/blob/main/ADOPTERS.md)
|
||||
@@ -1,3 +1,5 @@
|
||||
## Code of Conduct
|
||||
# Code of Conduct
|
||||
|
||||
The Kubescape project follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
|
||||
The Kubescape project manages this document in the central project repository.
|
||||
|
||||
Go to the [centralized CODE_OF_CONDUCT.md](https://github.com/kubescape/project-governance/blob/main/CODE_OF_CONDUCT.md)
|
||||
|
||||
5
COMMUNITY.md
Normal file
5
COMMUNITY.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Community
|
||||
|
||||
The Kubescape project manages this document in the central project repository.
|
||||
|
||||
Go to the [centralized COMMUNITY.md](https://github.com/kubescape/project-governance/blob/main/COMMUNITY.md)
|
||||
@@ -1,98 +1,5 @@
|
||||
# Contributing
|
||||
|
||||
First, it is awesome that you are considering contributing to Kubescape! Contributing is important and fun and we welcome your efforts.
|
||||
The Kubescape project manages this document in the central project repository.
|
||||
|
||||
When contributing, we categorize contributions into two:
|
||||
* Small code changes or fixes, whose scope is limited to a single or two files
|
||||
* Complex features and improvements, with potentially unlimited scope
|
||||
|
||||
If you have a small change, feel free to fire up a Pull Request.
|
||||
|
||||
When planning a bigger change, please first discuss the change you wish to make via an issue,
|
||||
so the maintainers are able to help guide you and let you know if you are going in the right direction.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
Please follow our [code of conduct](CODE_OF_CONDUCT.md) in all of your interactions within the project.
|
||||
|
||||
## Build and test locally
|
||||
|
||||
Please follow the [instructions here](https://github.com/kubescape/kubescape/wiki/Building).
|
||||
|
||||
## Pull Request Process
|
||||
|
||||
1. Ensure any install or build dependencies are removed before the end of the layer when doing a
|
||||
build.
|
||||
2. Update the README.md with details of changes to the interface, this includes new environment
|
||||
variables, exposed ports, useful file locations and container parameters.
|
||||
3. Open Pull Request to the `master` branch.
|
||||
4. We will merge the Pull Request once you have the sign-off.
|
||||
|
||||
## Developer Certificate of Origin
|
||||
|
||||
All commits to the project must be "signed off", which states that you agree to the terms of the [Developer Certificate of Origin](https://developercertificate.org/). This is done by adding a "Signed-off-by:" line in the commit message, with your name and email address.
|
||||
|
||||
Commits made through the GitHub web application are automatically signed off.
|
||||
|
||||
### Configuring Git to sign off commits
|
||||
|
||||
First, configure your name and email address in Git global settings:
|
||||
|
||||
```
|
||||
$ git config --global user.name "John Doe"
|
||||
$ git config --global user.email johndoe@example.com
|
||||
```
|
||||
|
||||
You can now sign off per-commit, or configure Git to always sign off commits per repository.
|
||||
|
||||
### Sign off per-commit
|
||||
|
||||
Add [`-s`](https://git-scm.com/docs/git-commit#Documentation/git-commit.txt--s) to your Git command line. For example:
|
||||
|
||||
```git commit -s -m "Fix issue 64738"```
|
||||
|
||||
This is tedious, and if you forget, you'll have to [amend your commit](#fixing-a-commit-where-the-dco-failed).
|
||||
|
||||
### Configure a repository to always include sign off
|
||||
|
||||
There are many ways to achieve this with Git hooks, but the simplest is to do the following:
|
||||
|
||||
```
|
||||
cd your-repo
|
||||
curl -Ls https://gist.githubusercontent.com/dixudx/7d7edea35b4d91e1a2a8fbf41d0954fa/raw/prepare-commit-msg -o .git/hooks/prepare-commit-msg
|
||||
chmod +x .git/hooks/prepare-commit-msg
|
||||
```
|
||||
|
||||
### Use semantic commit messages (optional)
|
||||
|
||||
When contributing, you could consider using [conventional commits](https://www.conventionalcommits.org/en/v1.0.0/), in order to improve logs readability and help us to automatically generate `CHANGELOG`s.
|
||||
|
||||
Format: `<type>(<scope>): <subject>`
|
||||
|
||||
`<scope>` is optional
|
||||
|
||||
#### Example
|
||||
|
||||
```
|
||||
feat(cmd): add kubectl plugin
|
||||
^--^ ^-^ ^----------------^
|
||||
| | |
|
||||
| | +-> subject: summary in present tense.
|
||||
| |
|
||||
| +-------> scope: point of interest
|
||||
|
|
||||
+-------> type: chore, docs, feat, fix, refactor, style, or test.
|
||||
```
|
||||
|
||||
More Examples:
|
||||
* `feat`: new feature for the user, not a new feature for build script
|
||||
* `fix`: bug fix for the user, not a fix to a build script
|
||||
* `docs`: changes to the documentation
|
||||
* `style`: formatting, missing semi colons, etc; no production code change
|
||||
* `refactor`: refactoring production code, eg. renaming a variable
|
||||
* `test`: adding missing tests, refactoring tests; no production code change
|
||||
* `chore`: updating grunt tasks etc; no production code change
|
||||
|
||||
## Fixing a commit where the DCO failed
|
||||
|
||||
Check out [this guide](https://github.com/src-d/guide/blob/master/developer-community/fix-DCO.md).
|
||||
Go to the [centralized CONTRIBUTING.md](https://github.com/kubescape/project-governance/blob/main/CONTRIBUTING.md)
|
||||
|
||||
@@ -1,65 +1,5 @@
|
||||
# Governance of Kubescape
|
||||
# Governance
|
||||
|
||||
## Overview
|
||||
The Kubescape project manages this document in the central project repository.
|
||||
|
||||
The Kubescape project is an open-source initiative dedicated to improve security and best practices in Kubernetes environments. This document outlines the governance structure of the Kubescape project and provides guidance for its community contributors.
|
||||
|
||||
## Decision Making
|
||||
|
||||
### Maintainers
|
||||
|
||||
- Maintainers are responsible for the smooth operation of the project.
|
||||
- They review and merge pull requests, manage releases, and ensure the quality and stability of the codebase.
|
||||
- Maintainers are chosen based on their ongoing contributions and their demonstrated commitment to the project.
|
||||
- Everyone who had at least 5 code contribution in the last 12 month can submit her/himself for joining the maintainer team
|
||||
- Maintainers who are not taken part in the project work (code, reviews, discussions) for 12 month are automaticaly removed from the maintainer team
|
||||
|
||||
|
||||
### Committers
|
||||
|
||||
- Committers are contributors who have made significant and consistent contributions to the project.
|
||||
- They have the ability to merge minor pull requests if assigned by maintainers.
|
||||
- A contributor can be proposed as a committer by any existing maintainer. The proposal will be reviewed and voted on by the existing maintainers.
|
||||
|
||||
### Community Members
|
||||
|
||||
- Anyone can become a community member by contributing to the project. This can be in the form of code contributions, documentation, or any other form of project support.
|
||||
|
||||
## Processes
|
||||
|
||||
### Proposing Changes
|
||||
|
||||
1. Open an issue on the project repository to discuss the proposed change.
|
||||
2. Once there is consensus around the proposed change, create a pull request.
|
||||
3. Pull requests will be reviewed by committers and/or maintainers.
|
||||
4. Once the pull request has received approval, it can be merged into the main codebase.
|
||||
|
||||
### Conflict Resolution
|
||||
|
||||
1. In case of any conflicts, it is primarily the responsibility of the parties involved to resolve it.
|
||||
2. If the conflict cannot be resolved, it will be escalated to the maintainers for resolution.
|
||||
3. Maintainers' decision will be final in case of unresolved conflicts.
|
||||
|
||||
## Roles and Responsibilities
|
||||
|
||||
### Maintainers
|
||||
|
||||
- Ensure the quality and stability of the project.
|
||||
- Resolve conflicts.
|
||||
- Provide direction and set priorities for the project.
|
||||
|
||||
### Committers
|
||||
|
||||
- Review and merge minor pull requests.
|
||||
- Assist maintainers in project tasks.
|
||||
- Promote best practices within the community.
|
||||
|
||||
### Community Members
|
||||
|
||||
- Contribute to the project in any form.
|
||||
- Participate in discussions and provide feedback.
|
||||
- Respect the code of conduct and governance of the project.
|
||||
|
||||
## Changes to the Governance Document
|
||||
|
||||
Proposed changes to this governance document should follow the same process as any other code change to the Kubescape project (see "Proposing Changes").
|
||||
Go to the [centralized GOVERNANCE.md](https://github.com/kubescape/project-governance/blob/main/GOVERNANCE.md)
|
||||
|
||||
@@ -1,12 +1,5 @@
|
||||
# Maintainers
|
||||
|
||||
The following table lists the Kubescape project core maintainers:
|
||||
|
||||
| Name | GitHub | Organization | Added/Renewed On |
|
||||
| --- | --- | --- | --- |
|
||||
| [Matthias Bertschy](https://www.linkedin.com/in/matthias-bertschy-b427b815/) | [@matthyx](https://github.com/matthyx) | [ARMO](https://www.armosec.io/) | 2023-01-01 |
|
||||
| [Craig Box](https://www.linkedin.com/in/crbnz/) | [@craigbox](https://github.com/craigbox) | [Solo.io](https://www.solo.io/) | 2022-10-31 |
|
||||
| [Ben Hirschberg](https://www.linkedin.com/in/benyamin-ben-hirschberg-66141890) | [@slashben](https://github.com/slashben) | [ARMO](https://www.armosec.io/) | 2021-09-01 |
|
||||
| [Rotem Refael](https://www.linkedin.com/in/rotem-refael) | [@rotemamsa](https://github.com/rotemamsa) | [ARMO](https://www.armosec.io/) | 2021-10-11 |
|
||||
| [David Wertenteil](https://www.linkedin.com/in/david-wertenteil-0ba277b9) | [@dwertent](https://github.com/dwertent) | [ARMO](https://www.armosec.io/) | 2021-09-01 |
|
||||
The Kubescape project manages this document in the central project repository.
|
||||
|
||||
Go to the [centralized MAINTAINERS.md](https://github.com/kubescape/project-governance/blob/main/MAINTAINERS.md)
|
||||
|
||||
67
README.md
67
README.md
@@ -20,21 +20,22 @@
|
||||
<img alt="Kubescape logo" align="right" src="https://raw.githubusercontent.com/cncf/artwork/master/projects/kubescape/stacked/color/kubescape-stacked-color.svg" width="150">
|
||||
</picture>
|
||||
|
||||
_An open-source Kubernetes security platform for your clusters, CI/CD pipelines, and IDE that seperates out the security signal from the scanner noise_
|
||||
_Comprehensive Kubernetes Security from Development to Runtime_
|
||||
|
||||
Kubescape is an open-source Kubernetes security platform, built for use in your day-to-day workflow, by fitting into your clusters, CI/CD pipelines and IDE. It serves as a one-stop-shop for Kuberenetes security and includes vulnerability and misconfiguration scanning. You can run scans via the CLI, or add the Kubescape Helm chart, which gives an in-depth view of what is going on in the cluster.
|
||||
Kubescape is an open-source Kubernetes security platform that provides comprehensive security coverage, from left to right across the entire development and deployment lifecycle. It offers hardening, posture management, and runtime security capabilities to ensure robust protection for Kubernetes environments. It saves Kubernetes users and admins precious time, effort, and resources.
|
||||
|
||||
Kubescape includes misconfiguration and vulnerability scanning as well as risk analysis and security compliance indicators. All results are presented in context and users get many cues on what to do based on scan results.Targeted at the DevSecOps practitioner or platform engineer, it offers an easy-to-use CLI interface, flexible output formats, and automated scanning capabilities. It saves Kubernetes users and admins precious time, effort, and resources.
|
||||
|
||||
Kubescape scans clusters, YAML files, and Helm charts. It detects misconfigurations according to multiple frameworks (including [NSA-CISA](https://www.armosec.io/blog/kubernetes-hardening-guidance-summary-by-armo/?utm_source=github&utm_medium=repository), [MITRE ATT&CK®](https://www.microsoft.com/security/blog/2021/03/23/secure-containerized-environments-with-updated-threat-matrix-for-kubernetes/) and the [CIS Benchmark](https://www.armosec.io/blog/cis-kubernetes-benchmark-framework-scanning-tools-comparison/?utm_source=github&utm_medium=repository)).
|
||||
Kubescape scans clusters, YAML files, and Helm charts. It detects misconfigurations according to multiple frameworks (including [NSA-CISA](https://www.armosec.io/blog/kubernetes-hardening-guidance-summary-by-armo/?utm_source=github&utm_medium=repository), [MITRE ATT&CK®](https://www.armosec.io/glossary/mitre-attck-framework/?utm_source=github&utm_medium=repository) and the [CIS Benchmark](https://www.armosec.io/blog/cis-kubernetes-benchmark-framework-scanning-tools-comparison/?utm_source=github&utm_medium=repository)).
|
||||
|
||||
Kubescape was created by [ARMO](https://www.armosec.io/?utm_source=github&utm_medium=repository) and is a [Cloud Native Computing Foundation (CNCF) sandbox project](https://www.cncf.io/sandbox-projects/).
|
||||
|
||||
## Demo
|
||||
<img src="docs/img/demo-v3.gif">
|
||||
|
||||
_Please [star ⭐](https://github.com/kubescape/kubescape/stargazers) the repo if you want us to continue developing and improving Kubescape! 😀_
|
||||
|
||||
## Demo
|
||||
|
||||
Kubescape has a command line tool that you can use to quickly get a report on the security posture of a Kubernetes cluster:
|
||||
|
||||
<img src="docs/img/demo-v3.gif">
|
||||
|
||||
## Getting started
|
||||
|
||||
Experimenting with Kubescape is as easy as:
|
||||
@@ -43,13 +44,13 @@ Experimenting with Kubescape is as easy as:
|
||||
curl -s https://raw.githubusercontent.com/kubescape/kubescape/master/install.sh | /bin/bash
|
||||
```
|
||||
|
||||
This script will automatically download the latest Kubescape CLI release and scan the Kubernetes cluster in your current kubectl context.
|
||||
|
||||
Learn more about:
|
||||
|
||||
* [Installing Kubescape](docs/installation.md)
|
||||
* [Running your first scan](docs/getting-started.md#run-your-first-scan)
|
||||
* [Usage](docs/getting-started.md#examples)
|
||||
* [Architecture](docs/architecture.md)
|
||||
* [Building Kubescape from source](https://github.com/kubescape/kubescape/wiki/Building)
|
||||
* [Installing the Kubescape CLI](https://kubescape.io/docs/install-cli/)
|
||||
* [Running your first scan](https://kubescape.io/docs/scanning/)
|
||||
* [Accepting risk with exceptions](https://kubescape.io/docs/accepting-risk/)
|
||||
|
||||
_Did you know you can use Kubescape in all these places?_
|
||||
|
||||
@@ -57,45 +58,47 @@ _Did you know you can use Kubescape in all these places?_
|
||||
<img src="docs/img/ksfromcodetodeploy.png" alt="Places you can use Kubescape: in your IDE, CI, CD, or against a running cluster.">
|
||||
</div>
|
||||
|
||||
## Kubescape-operator Helm-Chart
|
||||
### Continuous security monitoring with the Kubescape Operator
|
||||
|
||||
Besides the CLI, the Kubescape operator can also be installed via a Helm chart. Installing the Helm chart is an excellent way to begin using Kubescape, as it provides extensive features such as continuous scanning, image vulnerability scanning, runtime analysis, network policy generation, and more. You can find the Helm chart in the [Kubescape-operator documentation](https://kubescape.io/docs/install-operator/).
|
||||
As well as a CLI, Kubescape provides an in-cluster mode, which is installed via a Helm chart. Kubescape in-cluster provides extensive features such as continuous scanning, image vulnerability scanning, runtime analysis, network policy generation, and more. [Learn more about the Kubescape operator](https://kubescape.io/docs/operator/).
|
||||
|
||||
## Kubescape GitHub Action
|
||||
### Using Kubescape as a GitHub Action
|
||||
|
||||
Kubescape can be used as a GitHub Action. This is a great way to integrate Kubescape into your CI/CD pipeline. You can find the Kubescape GitHub Action in the [GitHub Action marketplace](https://github.com/marketplace/actions/kubescape).
|
||||
|
||||
## Under the hood
|
||||
|
||||
Kubescape uses [Open Policy Agent](https://github.com/open-policy-agent/opa) to verify Kubernetes objects against [a library of posture controls](https://github.com/kubescape/regolibrary).
|
||||
For image scanning, it uses [Grype](https://github.com/anchore/grype).
|
||||
For image patching, it uses [Copacetic](https://github.com/project-copacetic/copacetic).
|
||||
For eBPF, it uses [Inspektor Gadget](https://github.com/inspektor-gadget)
|
||||
|
||||
By default, the results are printed in a console-friendly manner, but they can be:
|
||||
By default, CLI scan results are printed in a console-friendly manner, but they can be:
|
||||
|
||||
* exported to JSON or junit XML
|
||||
* exported to JSON, junit XML or SARIF
|
||||
* rendered to HTML or PDF
|
||||
* submitted to a [cloud service](docs/providers.md)
|
||||
|
||||
It retrieves Kubernetes objects from the API server and runs a set of [Rego snippets](https://www.openpolicyagent.org/docs/latest/policy-language/) developed by [ARMO](https://www.armosec.io?utm_source=github&utm_medium=repository).
|
||||
### In-cluster architecture
|
||||
|
||||

|
||||
|
||||
## Community
|
||||
|
||||
Kubescape is an open source project, we welcome your feedback and ideas for improvement. We are part of the Kubernetes community and are building more tests and controls as the ecosystem develops.
|
||||
Kubescape is an open source project. We welcome your feedback and ideas for improvement. We are part of the CNCF community and are evolving Kubescape in sync with the security needs of Kubernetes users. To learn more about where Kubescape is heading, please check out our [ROADMAP](https://github.com/kubescape/project-governance/blob/main/ROADMAP.md).
|
||||
|
||||
We hold [community meetings](https://zoom.us/j/95174063585) on Zoom, every second week on Tuesdays, at 15:00 CET. ([See that in your local time zone](https://time.is/compare/1500_in_CET)).
|
||||
If you feel inspired to contribute to Kubescape, check out our [CONTRIBUTING](https://github.com/kubescape/project-governance/blob/main/CONTRIBUTING.md) file to learn how. You can find the issues we are working on (triage to development) on the [Kubescaping board](https://github.com/orgs/kubescape/projects/4/views/1)
|
||||
|
||||
* Feel free to pick a task from the [board](https://github.com/orgs/kubescape/projects/4) or suggest a feature of your own.
|
||||
* Open an issue on the board. We aim to respond to all issues within 48 hours.
|
||||
* [Join the CNCF Slack](https://slack.cncf.io/) and then our [users](https://cloud-native.slack.com/archives/C04EY3ZF9GE) or [developers](https://cloud-native.slack.com/archives/C04GY6H082K) channel.
|
||||
|
||||
The Kubescape project follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md).
|
||||
|
||||
### Adopters
|
||||
For more information about the Kubescape community, please visit [COMMUNITY](https://github.com/kubescape/project-governance/blob/main/COMMUNITY.md).
|
||||
|
||||
See [here](ADOPTERS.md) a list of adopters.
|
||||
|
||||
## Contributions
|
||||
|
||||
Thanks to all our contributors! Check out our [CONTRIBUTING](CONTRIBUTING.md) file to learn how to join them.
|
||||
|
||||
* Feel free to pick a task from the [issues](https://github.com/kubescape/kubescape/issues?q=is%3Aissue+is%3Aopen+label%3A%22open+for+contribution%22), [roadmap](docs/roadmap.md) or suggest a feature of your own.
|
||||
* [Open an issue](https://github.com/kubescape/kubescape/issues/new/choose): we aim to respond to all issues within 48 hours.
|
||||
* [Join the CNCF Slack](https://slack.cncf.io/) and then our [users](https://cloud-native.slack.com/archives/C04EY3ZF9GE) or [developers](https://cloud-native.slack.com/archives/C04GY6H082K) channel.
|
||||
We would like to take this opportunity to thank all our contibutors to date.
|
||||
|
||||
<br>
|
||||
|
||||
@@ -105,11 +108,11 @@ Thanks to all our contributors! Check out our [CONTRIBUTING](CONTRIBUTING.md) f
|
||||
|
||||
## Changelog
|
||||
|
||||
Kubescape changes are tracked on the [release](https://github.com/kubescape/kubescape/releases) page
|
||||
Kubescape changes are tracked on the [release](https://github.com/kubescape/kubescape/releases) page.
|
||||
|
||||
## License
|
||||
|
||||
Copyright 2021-2023, the Kubescape Authors. All rights reserved. Kubescape is released under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details.
|
||||
Copyright 2021-2024, the Kubescape Authors. All rights reserved. Kubescape is released under the Apache 2.0 license. See the [LICENSE](LICENSE) file for details.
|
||||
|
||||
Kubescape is a [Cloud Native Computing Foundation (CNCF) sandbox project](https://www.cncf.io/sandbox-projects/) and was contributed by [ARMO](https://www.armosec.io/?utm_source=github&utm_medium=repository).
|
||||
|
||||
|
||||
@@ -4,15 +4,19 @@ header:
|
||||
last-reviewed: '2023-10-12'
|
||||
expiration-date: '2024-10-12T01:00:00.000Z'
|
||||
project-url: https://github.com/kubescape/kubescape/
|
||||
project-release: '1.0.0'
|
||||
project-release: 1.0.0
|
||||
project-lifecycle:
|
||||
status: active
|
||||
bug-fixes-only: false
|
||||
core-maintainers:
|
||||
- github:slashben
|
||||
- github:amirmalka
|
||||
- github:amitschendel
|
||||
- github:bezbran
|
||||
- github:craigbox
|
||||
- github:matthyx
|
||||
- github:dwertent
|
||||
- github:matthyx
|
||||
- github:rotemamsa
|
||||
- github:slashben
|
||||
contribution-policy:
|
||||
accepts-pull-requests: true
|
||||
accepts-automated-pull-requests: false
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
# Reporting Security Issues
|
||||
# Security
|
||||
|
||||
To report a security issue or vulnerability, submit a [private vulnerability report via GitHub](https://github.com/kubescape/kubescape/security/advisories/new) to the repository maintainers with a description of the issue, the steps you took to create the issue, affected versions, and, if known, mitigations for the issue.
|
||||
The Kubescape project manages this document in the central project repository.
|
||||
|
||||
The maintainers will respond within 7 working days of your report. If the issue is confirmed as a vulnerability, we will open a Security Advisory and acknowledge your contributions as part of it. This project follows a 90 day disclosure timeline.
|
||||
|
||||
Other contacts: cncf-kubescape-maintainers@lists.cncf.io
|
||||
Go to the [centralized SECURITY.md](https://github.com/kubescape/project-governance/blob/main/SECURITY.md)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM --platform=$BUILDPLATFORM golang:1.22-bullseye as builder
|
||||
FROM --platform=$BUILDPLATFORM golang:1.23-bookworm AS builder
|
||||
|
||||
ENV GO111MODULE=on CGO_ENABLED=0
|
||||
WORKDIR /work
|
||||
@@ -8,13 +8,18 @@ RUN --mount=target=. \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=type=cache,target=/go/pkg \
|
||||
cd httphandler && GOOS=$TARGETOS GOARCH=$TARGETARCH go build -o /out/ksserver .
|
||||
RUN --mount=target=. \
|
||||
--mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=type=cache,target=/go/pkg \
|
||||
go run downloader/main.go
|
||||
|
||||
FROM gcr.io/distroless/static-debian11:nonroot
|
||||
FROM gcr.io/distroless/static-debian12:nonroot
|
||||
|
||||
USER nonroot
|
||||
WORKDIR /home/nonroot/
|
||||
|
||||
COPY --from=builder /out/ksserver /usr/bin/ksserver
|
||||
COPY --from=builder /root/.kubescape /home/nonroot/.kubescape
|
||||
|
||||
ARG image_version client
|
||||
ENV RELEASE=$image_version CLIENT=$client
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM gcr.io/distroless/base-debian11:debug-nonroot
|
||||
FROM gcr.io/distroless/static-debian12:debug-nonroot
|
||||
|
||||
USER nonroot
|
||||
WORKDIR /home/nonroot/
|
||||
|
||||
@@ -3,7 +3,7 @@ package config
|
||||
import (
|
||||
"context"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/kubescape/v3/core/meta"
|
||||
v1 "github.com/kubescape/kubescape/v3/core/meta/datastructures/v1"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/kubescape/v3/core/meta"
|
||||
metav1 "github.com/kubescape/kubescape/v3/core/meta/datastructures/v1"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@@ -3,7 +3,7 @@ package config
|
||||
import (
|
||||
"os"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/kubescape/v3/core/meta"
|
||||
v1 "github.com/kubescape/kubescape/v3/core/meta/datastructures/v1"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/core"
|
||||
"github.com/kubescape/kubescape/v3/core/meta"
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/meta"
|
||||
metav1 "github.com/kubescape/kubescape/v3/core/meta/datastructures/v1"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/core"
|
||||
"github.com/kubescape/kubescape/v3/core/meta"
|
||||
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/meta"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
||||
@@ -8,14 +8,12 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/distribution/reference"
|
||||
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/kubescape/v3/cmd/shared"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/meta"
|
||||
metav1 "github.com/kubescape/kubescape/v3/core/meta/datastructures/v1"
|
||||
"github.com/kubescape/kubescape/v3/pkg/imagescan"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"github.com/kubescape/kubescape/v3/core/cautils/getter"
|
||||
"github.com/kubescape/kubescape/v3/core/core"
|
||||
"github.com/kubescape/kubescape/v3/core/meta"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
||||
@@ -8,13 +8,12 @@ import (
|
||||
v1 "github.com/kubescape/backend/pkg/client/v1"
|
||||
"github.com/kubescape/backend/pkg/servicediscovery"
|
||||
sdClientV2 "github.com/kubescape/backend/pkg/servicediscovery/v2"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/go-logger/iconlogger"
|
||||
"github.com/kubescape/go-logger/zaplogger"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils/getter"
|
||||
|
||||
"github.com/mattn/go-isatty"
|
||||
)
|
||||
|
||||
|
||||
@@ -7,14 +7,12 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
apisv1 "github.com/kubescape/opa-utils/httpserver/apis/v1"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/cmd/shared"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/meta"
|
||||
|
||||
apisv1 "github.com/kubescape/opa-utils/httpserver/apis/v1"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
||||
@@ -8,19 +8,17 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
apisv1 "github.com/kubescape/opa-utils/httpserver/apis/v1"
|
||||
reporthandlingapis "github.com/kubescape/opa-utils/reporthandling/apis"
|
||||
"github.com/kubescape/opa-utils/reporthandling/results/v1/reportsummary"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/cmd/shared"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils/getter"
|
||||
"github.com/kubescape/kubescape/v3/core/meta"
|
||||
|
||||
apisv1 "github.com/kubescape/opa-utils/httpserver/apis/v1"
|
||||
reporthandlingapis "github.com/kubescape/opa-utils/reporthandling/apis"
|
||||
"github.com/kubescape/opa-utils/reporthandling/results/v1/reportsummary"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -4,13 +4,12 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/kubescape/v3/cmd/shared"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/meta"
|
||||
metav1 "github.com/kubescape/kubescape/v3/core/meta/datastructures/v1"
|
||||
"github.com/kubescape/kubescape/v3/pkg/imagescan"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils/getter"
|
||||
"github.com/kubescape/kubescape/v3/core/meta"
|
||||
@@ -15,12 +15,12 @@ import (
|
||||
)
|
||||
|
||||
var scanCmdExamples = fmt.Sprintf(`
|
||||
Scan command is for scanning an existing cluster or kubernetes manifest files based on pre-defined frameworks
|
||||
|
||||
Scan command is for scanning an existing cluster or kubernetes manifest files based on pre-defined frameworks
|
||||
|
||||
# Scan current cluster
|
||||
%[1]s scan
|
||||
|
||||
# Scan kubernetes manifest files
|
||||
# Scan kubernetes manifest files
|
||||
%[1]s scan .
|
||||
|
||||
# Scan and save the results in the JSON format
|
||||
@@ -29,7 +29,7 @@ var scanCmdExamples = fmt.Sprintf(`
|
||||
# Display all resources
|
||||
%[1]s scan --verbose
|
||||
|
||||
# Scan different clusters from the kubectl context
|
||||
# Scan different clusters from the kubectl context
|
||||
%[1]s scan --kube-context <kubernetes context>
|
||||
`, cautils.ExecName())
|
||||
|
||||
@@ -89,6 +89,7 @@ func GetScanCommand(ks meta.IKubescape) *cobra.Command {
|
||||
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")
|
||||
scanCmd.PersistentFlags().BoolVarP(&scanInfo.OmitRawResources, "omit-raw-resources", "", false, "Omit raw resources from the output. By default the raw resources are included in the output")
|
||||
scanCmd.PersistentFlags().BoolVarP(&scanInfo.PrintAttackTree, "print-attack-tree", "", false, "Print attack tree")
|
||||
scanCmd.PersistentFlags().BoolVarP(&scanInfo.EnableRegoPrint, "enable-rego-prints", "", false, "Enable sending to rego prints to the logs (use with debug log level: -l debug)")
|
||||
scanCmd.PersistentFlags().BoolVarP(&scanInfo.ScanImages, "scan-images", "", false, "Scan resources images")
|
||||
|
||||
scanCmd.PersistentFlags().MarkDeprecated("fail-threshold", "use '--compliance-threshold' flag instead. Flag will be removed at 1.Dec.2023")
|
||||
|
||||
@@ -2,20 +2,18 @@ package scan
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/kubescape/kubescape/v3/cmd/shared"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/mocks"
|
||||
v1 "github.com/kubescape/opa-utils/httpserver/apis/v1"
|
||||
"github.com/kubescape/opa-utils/reporthandling/apis"
|
||||
"github.com/kubescape/opa-utils/reporthandling/results/v1/reportsummary"
|
||||
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestExceedsSeverity(t *testing.T) {
|
||||
|
||||
@@ -6,12 +6,11 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/meta"
|
||||
v1 "github.com/kubescape/opa-utils/httpserver/apis/v1"
|
||||
"github.com/kubescape/opa-utils/objectsenvelopes"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/kubescape/backend/pkg/versioncheck"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@@ -9,11 +9,10 @@ import (
|
||||
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"sigs.k8s.io/yaml"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
admissionv1 "k8s.io/api/admissionregistration/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"sigs.k8s.io/yaml"
|
||||
)
|
||||
|
||||
var vapHelperCmdExamples = fmt.Sprintf(`
|
||||
@@ -203,7 +202,7 @@ func createPolicyBinding(bindingName string, policyName string, action string, p
|
||||
policyBinding.Spec.MatchResources.NamespaceSelector = &metav1.LabelSelector{
|
||||
MatchExpressions: []metav1.LabelSelectorRequirement{
|
||||
{
|
||||
Key: "name",
|
||||
Key: "kubernetes.io/metadata.name",
|
||||
Operator: metav1.LabelSelectorOpIn,
|
||||
Values: namespaceArr,
|
||||
},
|
||||
|
||||
@@ -7,18 +7,17 @@ import (
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
"github.com/google/uuid"
|
||||
v1 "github.com/kubescape/backend/pkg/client/v1"
|
||||
"github.com/kubescape/backend/pkg/servicediscovery"
|
||||
servicediscoveryv1 "github.com/kubescape/backend/pkg/servicediscovery/v1"
|
||||
servicediscoveryv2 "github.com/kubescape/backend/pkg/servicediscovery/v2"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils/getter"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
package cautils
|
||||
|
||||
import (
|
||||
"golang.org/x/mod/semver"
|
||||
|
||||
"github.com/kubescape/backend/pkg/versioncheck"
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
"github.com/kubescape/opa-utils/reporthandling/apis"
|
||||
reporthandlingv2 "github.com/kubescape/opa-utils/reporthandling/v2"
|
||||
"golang.org/x/mod/semver"
|
||||
)
|
||||
|
||||
func NewPolicies() *Policies {
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
|
||||
spinnerpkg "github.com/briandowns/spinner"
|
||||
"github.com/jwalton/gchalk"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/mattn/go-isatty"
|
||||
"github.com/schollz/progressbar/v3"
|
||||
|
||||
@@ -9,14 +9,12 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/opa-utils/objectsenvelopes"
|
||||
"github.com/kubescape/opa-utils/objectsenvelopes/localworkload"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -38,7 +36,7 @@ type Chart struct {
|
||||
}
|
||||
|
||||
// LoadResourcesFromHelmCharts scans a given path (recursively) for helm charts, renders the templates and returns a map of workloads and a map of chart names
|
||||
func LoadResourcesFromHelmCharts(ctx context.Context, basePath string) (map[string][]workloadinterface.IMetadata, map[string]Chart, map[string]MappingNodes) {
|
||||
func LoadResourcesFromHelmCharts(ctx context.Context, basePath string) (map[string][]workloadinterface.IMetadata, map[string]Chart) {
|
||||
directories, _ := listDirs(basePath)
|
||||
helmDirectories := make([]string, 0)
|
||||
for _, dir := range directories {
|
||||
@@ -49,19 +47,14 @@ func LoadResourcesFromHelmCharts(ctx context.Context, basePath string) (map[stri
|
||||
|
||||
sourceToWorkloads := map[string][]workloadinterface.IMetadata{}
|
||||
sourceToChart := make(map[string]Chart, 0)
|
||||
sourceToNodes := map[string]MappingNodes{}
|
||||
for _, helmDir := range helmDirectories {
|
||||
chart, err := NewHelmChart(helmDir)
|
||||
if err == nil {
|
||||
wls, templateToNodes, errs := chart.GetWorkloadsWithDefaultValues()
|
||||
wls, errs := chart.GetWorkloadsWithDefaultValues()
|
||||
if len(errs) > 0 {
|
||||
logger.L().Ctx(ctx).Warning(fmt.Sprintf("Rendering of Helm chart template '%s', failed: %v", chart.GetName(), errs))
|
||||
continue
|
||||
}
|
||||
for k, v := range templateToNodes {
|
||||
sourceToNodes[k] = v
|
||||
}
|
||||
|
||||
chartName := chart.GetName()
|
||||
for k, v := range wls {
|
||||
sourceToWorkloads[k] = v
|
||||
@@ -72,7 +65,7 @@ func LoadResourcesFromHelmCharts(ctx context.Context, basePath string) (map[stri
|
||||
}
|
||||
}
|
||||
}
|
||||
return sourceToWorkloads, sourceToChart, sourceToNodes
|
||||
return sourceToWorkloads, sourceToChart
|
||||
}
|
||||
|
||||
// If the contents at given path is a Kustomize Directory, LoadResourcesFromKustomizeDirectory will
|
||||
|
||||
@@ -45,7 +45,7 @@ func TestLoadResourcesFromFiles(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestLoadResourcesFromHelmCharts(t *testing.T) {
|
||||
sourceToWorkloads, sourceToChartName, _ := LoadResourcesFromHelmCharts(context.TODO(), helmChartPath())
|
||||
sourceToWorkloads, sourceToChartName := LoadResourcesFromHelmCharts(context.TODO(), helmChartPath())
|
||||
assert.Equal(t, 6, len(sourceToWorkloads))
|
||||
|
||||
for file, workloads := range sourceToWorkloads {
|
||||
|
||||
@@ -5,10 +5,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/armosec/armoapi-go/armotypes"
|
||||
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
"github.com/kubescape/opa-utils/reporthandling/attacktrack/v1alpha1"
|
||||
|
||||
"github.com/kubescape/regolibrary/v2/gitregostore"
|
||||
)
|
||||
|
||||
|
||||
@@ -5,11 +5,10 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/opa-utils/objectsenvelopes/localworkload"
|
||||
|
||||
helmchart "helm.sh/helm/v3/pkg/chart"
|
||||
helmloader "helm.sh/helm/v3/pkg/chart/loader"
|
||||
helmchartutil "helm.sh/helm/v3/pkg/chartutil"
|
||||
@@ -45,35 +44,24 @@ func (hc *HelmChart) GetDefaultValues() map[string]interface{} {
|
||||
return hc.chart.Values
|
||||
}
|
||||
|
||||
// GetWorkloads renders chart template using the default values and returns a map of source file to its workloads
|
||||
func (hc *HelmChart) GetWorkloadsWithDefaultValues() (map[string][]workloadinterface.IMetadata, map[string]MappingNodes, []error) {
|
||||
// GetWorkloadsWithDefaultValues renders chart template using the default values and returns a map of source file to its workloads
|
||||
func (hc *HelmChart) GetWorkloadsWithDefaultValues() (map[string][]workloadinterface.IMetadata, []error) {
|
||||
return hc.GetWorkloads(hc.GetDefaultValues())
|
||||
}
|
||||
|
||||
// GetWorkloads renders chart template using the provided values and returns a map of source (absolute) file path to its workloads
|
||||
func (hc *HelmChart) GetWorkloads(values map[string]interface{}) (map[string][]workloadinterface.IMetadata, map[string]MappingNodes, []error) {
|
||||
func (hc *HelmChart) GetWorkloads(values map[string]interface{}) (map[string][]workloadinterface.IMetadata, []error) {
|
||||
vals, err := helmchartutil.ToRenderValues(hc.chart, values, helmchartutil.ReleaseOptions{}, nil)
|
||||
if err != nil {
|
||||
return nil, nil, []error{err}
|
||||
return nil, []error{err}
|
||||
}
|
||||
|
||||
// change the chart to template with comment, only is template(.yaml added otherwise no)
|
||||
hc.AddCommentToTemplate()
|
||||
|
||||
sourceToFile, err := helmengine.Render(hc.chart, vals)
|
||||
if err != nil {
|
||||
return nil, nil, []error{err}
|
||||
return nil, []error{err}
|
||||
}
|
||||
|
||||
// get the resouse and analysis and store it to the struct
|
||||
fileMapping := make(map[string]MappingNodes)
|
||||
GetTemplateMapping(sourceToFile, fileMapping)
|
||||
|
||||
// delete the comment from chart and from sourceToFile
|
||||
RemoveComment(sourceToFile)
|
||||
|
||||
workloads := make(map[string][]workloadinterface.IMetadata, 0)
|
||||
errs := []error{}
|
||||
workloads := make(map[string][]workloadinterface.IMetadata)
|
||||
var errs []error
|
||||
|
||||
for path, renderedYaml := range sourceToFile {
|
||||
if !IsYaml(strings.ToLower(path)) {
|
||||
@@ -87,13 +75,9 @@ func (hc *HelmChart) GetWorkloads(values map[string]interface{}) (map[string][]w
|
||||
if len(wls) == 0 {
|
||||
continue
|
||||
}
|
||||
if firstPathSeparatorIndex := strings.Index(path, string("/")); firstPathSeparatorIndex != -1 {
|
||||
if firstPathSeparatorIndex := strings.Index(path, "/"); firstPathSeparatorIndex != -1 {
|
||||
absPath := filepath.Join(hc.path, path[firstPathSeparatorIndex:])
|
||||
|
||||
if nodes, ok := fileMapping[path]; ok {
|
||||
fileMapping[absPath] = nodes
|
||||
delete(fileMapping, path)
|
||||
}
|
||||
workloads[absPath] = []workloadinterface.IMetadata{}
|
||||
for i := range wls {
|
||||
lw := localworkload.NewLocalWorkload(wls[i].GetObject())
|
||||
@@ -102,7 +86,7 @@ func (hc *HelmChart) GetWorkloads(values map[string]interface{}) (map[string][]w
|
||||
}
|
||||
}
|
||||
}
|
||||
return workloads, fileMapping, errs
|
||||
return workloads, errs
|
||||
}
|
||||
|
||||
func (hc *HelmChart) AddCommentToTemplate() {
|
||||
@@ -121,27 +105,3 @@ func (hc *HelmChart) AddCommentToTemplate() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func RemoveComment(sourceToFile map[string]string) {
|
||||
// commentRe := regexp.MustCompile(CommentFormat)
|
||||
for fileName, file := range sourceToFile {
|
||||
if !IsYaml(strings.ToLower((fileName))) {
|
||||
continue
|
||||
}
|
||||
sourceToFile[fileName] = commentRe.ReplaceAllLiteralString(file, "")
|
||||
}
|
||||
}
|
||||
|
||||
func GetTemplateMapping(sourceToFile map[string]string, fileMapping map[string]MappingNodes) {
|
||||
for fileName, fileContent := range sourceToFile {
|
||||
mappingNodes, err := GetMapping(fileName, fileContent)
|
||||
if err != nil {
|
||||
// if one file cannot get mapping nodes, generate error, then ignore it
|
||||
logger.L().Warning("Failed to get File Mapping nodes", helpers.String("file name", fileName), helpers.Error(err))
|
||||
continue
|
||||
}
|
||||
if len(mappingNodes.Nodes) != 0 {
|
||||
fileMapping[fileName] = *mappingNodes
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ func (s *HelmChartTestSuite) TestGetWorkloadsWithOverride() {
|
||||
// Override default value
|
||||
values["image"].(map[string]interface{})["pullPolicy"] = "Never"
|
||||
|
||||
fileToWorkloads, _, errs := chart.GetWorkloads(values)
|
||||
fileToWorkloads, errs := chart.GetWorkloads(values)
|
||||
s.Len(errs, 0)
|
||||
|
||||
s.Lenf(fileToWorkloads, len(s.expectedFiles), "Expected %d files", len(s.expectedFiles))
|
||||
@@ -111,7 +111,7 @@ func (s *HelmChartTestSuite) TestGetWorkloadsMissingValue() {
|
||||
values := chart.GetDefaultValues()
|
||||
delete(values, "image")
|
||||
|
||||
fileToWorkloads, _, errs := chart.GetWorkloads(values)
|
||||
fileToWorkloads, errs := chart.GetWorkloads(values)
|
||||
s.Nil(fileToWorkloads)
|
||||
s.Len(errs, 1, "Expected an error due to missing value")
|
||||
|
||||
|
||||
@@ -4,11 +4,10 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/opa-utils/objectsenvelopes/localworkload"
|
||||
|
||||
"sigs.k8s.io/kustomize/api/krusty"
|
||||
"sigs.k8s.io/kustomize/kyaml/filesys"
|
||||
)
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/mikefarah/yq/v4/pkg/yqlib"
|
||||
"gopkg.in/op/go-logging.v1"
|
||||
)
|
||||
|
||||
@@ -4,10 +4,9 @@ import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
reporthandlingv2 "github.com/kubescape/opa-utils/reporthandling/v2"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
reporthandlingv2 "github.com/kubescape/opa-utils/reporthandling/v2"
|
||||
"github.com/kubescape/rbac-utils/rbacscanner"
|
||||
"github.com/kubescape/rbac-utils/rbacutils"
|
||||
)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/kubescape/backend/pkg/versioncheck"
|
||||
giturl "github.com/kubescape/go-git-url"
|
||||
"github.com/kubescape/go-logger"
|
||||
@@ -18,8 +19,6 @@ import (
|
||||
"github.com/kubescape/opa-utils/objectsenvelopes"
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
reporthandlingv2 "github.com/kubescape/opa-utils/reporthandling/v2"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type ScanningContext string
|
||||
@@ -132,6 +131,7 @@ type ScanInfo struct {
|
||||
ScanAll bool // true if scan all frameworks
|
||||
OmitRawResources bool // true if omit raw resources from the output
|
||||
PrintAttackTree bool // true if print attack tree
|
||||
EnableRegoPrint bool // true if print rego
|
||||
ScanObject *objectsenvelopes.ScanObject // identifies a single resource (k8s object) to be scanned
|
||||
IsDeletedScanObject bool // indicates whether the ScanObject is a deleted K8S resource
|
||||
ScanType ScanTypes
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils/getter"
|
||||
|
||||
@@ -5,9 +5,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
metav1 "github.com/kubescape/kubescape/v3/core/meta/datastructures/v1"
|
||||
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/fixhandler"
|
||||
)
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/anchore/grype/grype/presenter/models"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
ksmetav1 "github.com/kubescape/kubescape/v3/core/meta/datastructures/v1"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling"
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
@@ -16,11 +17,8 @@ import (
|
||||
printerv2 "github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer/v2"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/reporter"
|
||||
reporterv2 "github.com/kubescape/kubescape/v3/core/pkg/resultshandling/reporter/v2"
|
||||
"go.opentelemetry.io/otel"
|
||||
|
||||
"github.com/google/uuid"
|
||||
|
||||
"github.com/kubescape/rbac-utils/rbacscanner"
|
||||
"go.opentelemetry.io/otel"
|
||||
)
|
||||
|
||||
// getKubernetesApi
|
||||
@@ -277,7 +275,7 @@ func getAttackTracksGetter(ctx context.Context, attackTracks, accountID string,
|
||||
return downloadReleasedPolicy
|
||||
}
|
||||
|
||||
// getUIPrinter returns a printer that will be used to print to the program’s UI (terminal)
|
||||
// GetUIPrinter returns a printer that will be used to print to the program’s UI (terminal)
|
||||
func GetUIPrinter(ctx context.Context, scanInfo *cautils.ScanInfo, clusterName string) printer.IPrinter {
|
||||
var p printer.IPrinter
|
||||
if helpers.ToLevel(logger.L().GetLevel()) >= helpers.WarningLevel {
|
||||
|
||||
@@ -9,22 +9,19 @@ import (
|
||||
|
||||
"github.com/anchore/grype/grype/presenter"
|
||||
"github.com/anchore/grype/grype/presenter/models"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
copaGrype "github.com/anubhav06/copa-grype/grype"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
ksmetav1 "github.com/kubescape/kubescape/v3/core/meta/datastructures/v1"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer"
|
||||
"github.com/kubescape/kubescape/v3/pkg/imagescan"
|
||||
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling"
|
||||
log "github.com/sirupsen/logrus"
|
||||
|
||||
copaGrype "github.com/anubhav06/copa-grype/grype"
|
||||
"github.com/project-copacetic/copacetic/pkg/buildkit"
|
||||
"github.com/project-copacetic/copacetic/pkg/pkgmgr"
|
||||
"github.com/project-copacetic/copacetic/pkg/types/unversioned"
|
||||
"github.com/project-copacetic/copacetic/pkg/utils"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func (ks *Kubescape) Patch(ctx context.Context, patchInfo *ksmetav1.PatchInfo, scanInfo *cautils.ScanInfo) (*models.PresenterConfig, error) {
|
||||
|
||||
@@ -21,11 +21,10 @@ import (
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/reporter"
|
||||
"github.com/kubescape/kubescape/v3/pkg/imagescan"
|
||||
apisv1 "github.com/kubescape/opa-utils/httpserver/apis/v1"
|
||||
"github.com/kubescape/opa-utils/resources"
|
||||
"go.opentelemetry.io/otel"
|
||||
"golang.org/x/exp/slices"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
|
||||
"github.com/kubescape/opa-utils/resources"
|
||||
)
|
||||
|
||||
type componentInterfaces struct {
|
||||
@@ -169,7 +168,7 @@ func (ks *Kubescape) Scan(ctx context.Context, scanInfo *cautils.ScanInfo) (*res
|
||||
|
||||
// ===================== resources =====================
|
||||
ctxResources, spanResources := otel.Tracer("").Start(ctxInit, "resources")
|
||||
err = resourcehandler.CollectResources(ctxResources, interfaces.resourceHandler, scanInfo.PolicyIdentifier, scanData, cautils.NewProgressHandler(""), scanInfo)
|
||||
err = resourcehandler.CollectResources(ctxResources, interfaces.resourceHandler, scanData, scanInfo)
|
||||
if err != nil {
|
||||
spanInit.End()
|
||||
return resultsHandling, err
|
||||
@@ -182,7 +181,7 @@ func (ks *Kubescape) Scan(ctx context.Context, scanInfo *cautils.ScanInfo) (*res
|
||||
defer spanOpa.End()
|
||||
|
||||
deps := resources.NewRegoDependenciesData(k8sinterface.GetK8sConfig(), interfaces.tenantConfig.GetContextName())
|
||||
reportResults := opaprocessor.NewOPAProcessor(scanData, deps, interfaces.tenantConfig.GetContextName())
|
||||
reportResults := opaprocessor.NewOPAProcessor(scanData, deps, interfaces.tenantConfig.GetContextName(), scanInfo.ExcludedNamespaces, scanInfo.IncludeNamespaces, scanInfo.EnableRegoPrint)
|
||||
if err = reportResults.ProcessRulesListener(ctxOpa, cautils.NewProgressHandler("")); err != nil {
|
||||
// TODO - do something
|
||||
return resultsHandling, fmt.Errorf("%w", err)
|
||||
|
||||
@@ -8,10 +8,8 @@ type SetConfig struct {
|
||||
CloudReportURL string
|
||||
CloudAPIURL string
|
||||
}
|
||||
|
||||
type ViewConfig struct {
|
||||
Writer io.Writer
|
||||
}
|
||||
|
||||
type DeleteConfig struct {
|
||||
}
|
||||
|
||||
@@ -13,9 +13,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/armosec/armoapi-go/armotypes"
|
||||
"github.com/kubescape/go-logger"
|
||||
metav1 "github.com/kubescape/kubescape/v3/core/meta/datastructures/v1"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/opa-utils/objectsenvelopes"
|
||||
"github.com/kubescape/opa-utils/objectsenvelopes/localworkload"
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/armosec/armoapi-go/armotypes"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
metav1 "github.com/kubescape/kubescape/v3/core/meta/datastructures/v1"
|
||||
"github.com/kubescape/kubescape/v3/internal/testutils"
|
||||
reporthandlingv2 "github.com/kubescape/opa-utils/reporthandling/v2"
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/mikefarah/yq/v4/pkg/yqlib"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/mikefarah/yq/v4/pkg/yqlib"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -8,12 +8,11 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
"github.com/kubescape/opa-utils/objectsenvelopes/hostsensor"
|
||||
"github.com/kubescape/opa-utils/reporthandling/apis"
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/opa-utils/objectsenvelopes/hostsensor"
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"crypto"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/go-containerregistry/pkg/name"
|
||||
"github.com/sigstore/cosign/v2/cmd/cosign/cli/options"
|
||||
"github.com/sigstore/cosign/v2/cmd/cosign/cli/sign"
|
||||
|
||||
@@ -2,8 +2,9 @@ package opaprocessor
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func Test_verify(t *testing.T) {
|
||||
|
||||
@@ -3,10 +3,11 @@ package opaprocessor
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/armosec/armoapi-go/armotypes"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
@@ -20,6 +21,7 @@ import (
|
||||
"github.com/open-policy-agent/opa/ast"
|
||||
"github.com/open-policy-agent/opa/rego"
|
||||
"github.com/open-policy-agent/opa/storage"
|
||||
opaprint "github.com/open-policy-agent/opa/topdown/print"
|
||||
"go.opentelemetry.io/otel"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
@@ -37,10 +39,13 @@ type OPAProcessor struct {
|
||||
clusterName string
|
||||
regoDependenciesData *resources.RegoDependenciesData
|
||||
*cautils.OPASessionObj
|
||||
opaRegisterOnce sync.Once
|
||||
opaRegisterOnce sync.Once
|
||||
excludeNamespaces []string
|
||||
includeNamespaces []string
|
||||
printEnabled bool
|
||||
}
|
||||
|
||||
func NewOPAProcessor(sessionObj *cautils.OPASessionObj, regoDependenciesData *resources.RegoDependenciesData, clusterName string) *OPAProcessor {
|
||||
func NewOPAProcessor(sessionObj *cautils.OPASessionObj, regoDependenciesData *resources.RegoDependenciesData, clusterName string, excludeNamespaces string, includeNamespaces string, enableRegoPrint bool) *OPAProcessor {
|
||||
if regoDependenciesData != nil && sessionObj != nil {
|
||||
regoDependenciesData.PostureControlInputs = sessionObj.RegoInputData.PostureControlInputs
|
||||
regoDependenciesData.DataControlInputs = sessionObj.RegoInputData.DataControlInputs
|
||||
@@ -50,6 +55,9 @@ func NewOPAProcessor(sessionObj *cautils.OPASessionObj, regoDependenciesData *re
|
||||
OPASessionObj: sessionObj,
|
||||
regoDependenciesData: regoDependenciesData,
|
||||
clusterName: clusterName,
|
||||
excludeNamespaces: split(excludeNamespaces),
|
||||
includeNamespaces: split(includeNamespaces),
|
||||
printEnabled: enableRegoPrint,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,6 +219,9 @@ func (opap *OPAProcessor) processRule(ctx context.Context, rule *reporthandling.
|
||||
inputResources = objectsenvelopes.ListMapToMeta(enumeratedData)
|
||||
|
||||
for i, inputResource := range inputResources {
|
||||
if opap.skipNamespace(inputResource.GetNamespace()) {
|
||||
continue
|
||||
}
|
||||
resources[inputResource.GetID()] = &resourcesresults.ResourceAssociatedRule{
|
||||
Name: rule.Name,
|
||||
ControlConfigurations: ruleRegoDependenciesData.PostureControlInputs,
|
||||
@@ -229,6 +240,9 @@ func (opap *OPAProcessor) processRule(ctx context.Context, rule *reporthandling.
|
||||
for _, ruleResponse := range ruleResponses {
|
||||
failedResources := objectsenvelopes.ListMapToMeta(ruleResponse.GetFailedResources())
|
||||
for _, failedResource := range failedResources {
|
||||
if opap.skipNamespace(failedResource.GetNamespace()) {
|
||||
continue
|
||||
}
|
||||
var ruleResult *resourcesresults.ResourceAssociatedRule
|
||||
if r, found := resources[failedResource.GetID()]; found {
|
||||
ruleResult = r
|
||||
@@ -308,7 +322,9 @@ func (opap *OPAProcessor) runRegoOnK8s(ctx context.Context, rule *reporthandling
|
||||
modules[rule.Name] = getRuleData(rule)
|
||||
|
||||
// NOTE: OPA module compilation is the most resource-intensive operation.
|
||||
compiled, err := ast.CompileModules(modules)
|
||||
compiled, err := ast.CompileModulesWithOpt(modules, ast.CompileOpts{
|
||||
EnablePrintStatements: opap.printEnabled,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("in 'runRegoOnK8s', failed to compile rule, name: %s, reason: %w", rule.Name, err)
|
||||
}
|
||||
@@ -327,12 +343,20 @@ func (opap *OPAProcessor) runRegoOnK8s(ctx context.Context, rule *reporthandling
|
||||
return results, nil
|
||||
}
|
||||
|
||||
func (opap *OPAProcessor) Print(ctx opaprint.Context, str string) error {
|
||||
msg := fmt.Sprintf("opa-print: {%v} - %s", ctx.Location, str)
|
||||
logger.L().Ctx(ctx.Context).Debug(msg)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (opap *OPAProcessor) regoEval(ctx context.Context, inputObj []map[string]interface{}, compiledRego *ast.Compiler, store *storage.Store) ([]reporthandling.RuleResponse, error) {
|
||||
rego := rego.New(
|
||||
rego.Query("data.armo_builtins"), // get package name from rule
|
||||
rego.Compiler(compiledRego),
|
||||
rego.Input(inputObj),
|
||||
rego.Store(*store),
|
||||
rego.EnablePrintStatements(opap.printEnabled),
|
||||
rego.PrintHook(opap),
|
||||
)
|
||||
|
||||
// Run evaluation
|
||||
@@ -387,3 +411,25 @@ func (opap *OPAProcessor) makeRegoDeps(configInputs []reporthandling.ControlConf
|
||||
PostureControlInputs: postureControlInputs,
|
||||
}
|
||||
}
|
||||
|
||||
func (opap *OPAProcessor) skipNamespace(ns string) bool {
|
||||
if includeNamespaces := opap.includeNamespaces; len(includeNamespaces) > 0 {
|
||||
if !slices.Contains(includeNamespaces, ns) {
|
||||
// skip ns not in IncludeNamespaces
|
||||
return true
|
||||
}
|
||||
} else if excludeNamespaces := opap.excludeNamespaces; len(excludeNamespaces) > 0 {
|
||||
if slices.Contains(excludeNamespaces, ns) {
|
||||
// skip ns in ExcludeNamespaces
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func split(namespaces string) []string {
|
||||
if namespaces == "" {
|
||||
return nil
|
||||
}
|
||||
return strings.Split(namespaces, ",")
|
||||
}
|
||||
|
||||
@@ -14,14 +14,13 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/armosec/armoapi-go/armotypes"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/mocks"
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
"github.com/kubescape/opa-utils/reporthandling/results/v1/resourcesresults"
|
||||
"github.com/kubescape/opa-utils/resources"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -197,7 +196,7 @@ func TestProcessResourcesResult(t *testing.T) {
|
||||
opaSessionObj.K8SResources = k8sResources
|
||||
opaSessionObj.AllResources[deployment.GetID()] = deployment
|
||||
|
||||
opap := NewOPAProcessor(opaSessionObj, resources.NewRegoDependenciesDataMock(), "test")
|
||||
opap := NewOPAProcessor(opaSessionObj, resources.NewRegoDependenciesDataMock(), "test", "", "", false)
|
||||
opap.AllPolicies = policies
|
||||
opap.Process(context.TODO(), policies, nil)
|
||||
|
||||
|
||||
@@ -3,9 +3,7 @@ package opaprocessor
|
||||
import (
|
||||
"context"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
@@ -16,6 +14,7 @@ import (
|
||||
"github.com/kubescape/opa-utils/reporthandling/results/v1/resourcesresults"
|
||||
resources "github.com/kubescape/opa-utils/resources"
|
||||
"go.opentelemetry.io/otel"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
const clusterScope = "clusterScope"
|
||||
|
||||
@@ -3,11 +3,9 @@ package opaprocessor
|
||||
import (
|
||||
"testing"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/stretchr/testify/assert"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
func TestRemoveData(t *testing.T) {
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
|
||||
@@ -3,13 +3,12 @@ package opaprocessor
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/mocks"
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
"github.com/kubescape/opa-utils/reporthandling/results/v1/reportsummary"
|
||||
v2 "github.com/kubescape/opa-utils/reporthandling/v2"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestConvertFrameworksToPolicies(t *testing.T) {
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/armosec/armoapi-go/armotypes"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils/getter"
|
||||
@@ -158,8 +158,11 @@ func (policyHandler *PolicyHandler) downloadScanPolicies(ctx context.Context, po
|
||||
if receivedFramework != nil {
|
||||
frameworks = append(frameworks, *receivedFramework)
|
||||
cache := getter.GetDefaultPath(rule.Identifier + ".json")
|
||||
if _, ok := policyHandler.getters.PolicyGetter.(*getter.LoadPolicy); ok {
|
||||
continue // skip caching for local files
|
||||
}
|
||||
if err := getter.SaveInFile(receivedFramework, cache); err != nil {
|
||||
logger.L().Ctx(ctx).Warning("failed to cache file", helpers.String("file", cache), helpers.Error(err))
|
||||
logger.L().Ctx(ctx).Warning("failed to cache framework", helpers.String("file", cache), helpers.Error(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -178,7 +181,7 @@ func (policyHandler *PolicyHandler) downloadScanPolicies(ctx context.Context, po
|
||||
|
||||
cache := getter.GetDefaultPath(policy.Identifier + ".json")
|
||||
if err := getter.SaveInFile(receivedControl, cache); err != nil {
|
||||
logger.L().Ctx(ctx).Warning("failed to cache file", helpers.String("file", cache), helpers.Error(err))
|
||||
logger.L().Ctx(ctx).Warning("failed to cache control", helpers.String("file", cache), helpers.Error(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,10 +5,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
apisv1 "github.com/kubescape/opa-utils/httpserver/apis/v1"
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
)
|
||||
|
||||
func getScanKind(policyIdentifier []cautils.PolicyIdentifier) apisv1.NotificationPolicyKind {
|
||||
|
||||
@@ -6,15 +6,13 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/opaprocessor"
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
)
|
||||
|
||||
// FileResourceHandler handle resources from files and URLs
|
||||
@@ -25,7 +23,7 @@ func NewFileResourceHandler() *FileResourceHandler {
|
||||
return &FileResourceHandler{}
|
||||
}
|
||||
|
||||
func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessionObj *cautils.OPASessionObj, _ opaprocessor.IJobProgressNotificationClient, scanInfo *cautils.ScanInfo) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.ExternalResources, map[string]bool, error) {
|
||||
func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessionObj *cautils.OPASessionObj, scanInfo *cautils.ScanInfo) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.ExternalResources, map[string]bool, error) {
|
||||
allResources := map[string]workloadinterface.IMetadata{}
|
||||
externalResources := cautils.ExternalResources{}
|
||||
|
||||
@@ -40,16 +38,12 @@ func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessio
|
||||
for path := range scanInfo.InputPatterns {
|
||||
var workloadIDToSource map[string]reporthandling.Source
|
||||
var workloads []workloadinterface.IMetadata
|
||||
var workloadIDToMappingNodes map[string]cautils.MappingNodes
|
||||
var err error
|
||||
|
||||
if scanInfo.ChartPath != "" && scanInfo.FilePath != "" {
|
||||
workloadIDToSource, workloads, workloadIDToMappingNodes, err = getWorkloadFromHelmChart(ctx, scanInfo.InputPatterns[path], scanInfo.ChartPath, scanInfo.FilePath)
|
||||
if err != nil {
|
||||
// We should probably ignore the error so we can continue scanning other charts
|
||||
}
|
||||
workloadIDToSource, workloads, _ = getWorkloadFromHelmChart(ctx, scanInfo.InputPatterns[path], scanInfo.ChartPath, scanInfo.FilePath)
|
||||
} else {
|
||||
workloadIDToSource, workloads, workloadIDToMappingNodes, err = getResourcesFromPath(ctx, scanInfo.InputPatterns[path])
|
||||
workloadIDToSource, workloads, err = getResourcesFromPath(ctx, scanInfo.InputPatterns[path])
|
||||
if err != nil {
|
||||
return nil, allResources, nil, nil, err
|
||||
}
|
||||
@@ -60,7 +54,7 @@ func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessio
|
||||
|
||||
for k, v := range workloadIDToSource {
|
||||
sessionObj.ResourceSource[k] = v
|
||||
sessionObj.TemplateMapping[k] = workloadIDToMappingNodes[k]
|
||||
sessionObj.TemplateMapping[k] = cautils.MappingNodes{}
|
||||
}
|
||||
|
||||
// map all resources: map["/apiVersion/version/kind"][]<k8s workloads>
|
||||
@@ -106,7 +100,7 @@ func (fileHandler *FileResourceHandler) GetResources(ctx context.Context, sessio
|
||||
func (fileHandler *FileResourceHandler) GetCloudProvider() string {
|
||||
return ""
|
||||
}
|
||||
func getWorkloadFromHelmChart(ctx context.Context, path, helmPath, workloadPath string) (map[string]reporthandling.Source, []workloadinterface.IMetadata, map[string]cautils.MappingNodes, error) {
|
||||
func getWorkloadFromHelmChart(ctx context.Context, path, helmPath, workloadPath string) (map[string]reporthandling.Source, []workloadinterface.IMetadata, error) {
|
||||
clonedRepo := cautils.GetClonedPath(path)
|
||||
|
||||
if clonedRepo != "" {
|
||||
@@ -120,38 +114,31 @@ func getWorkloadFromHelmChart(ctx context.Context, path, helmPath, workloadPath
|
||||
// Get repo root
|
||||
repoRoot, gitRepo := extractGitRepo(clonedRepo)
|
||||
|
||||
helmSourceToWorkloads, helmSourceToChart, helmSourceToNodes := cautils.LoadResourcesFromHelmCharts(ctx, helmPath)
|
||||
helmSourceToWorkloads, helmSourceToChart := cautils.LoadResourcesFromHelmCharts(ctx, helmPath)
|
||||
|
||||
wlSource, ok := helmSourceToWorkloads[workloadPath]
|
||||
if !ok {
|
||||
return nil, nil, nil, fmt.Errorf("workload %s not found in chart %s", workloadPath, helmPath)
|
||||
return nil, nil, fmt.Errorf("workload %s not found in chart %s", workloadPath, helmPath)
|
||||
}
|
||||
|
||||
if len(wlSource) != 1 {
|
||||
return nil, nil, nil, fmt.Errorf("workload %s found multiple times in chart %s", workloadPath, helmPath)
|
||||
return nil, nil, fmt.Errorf("workload %s found multiple times in chart %s", workloadPath, helmPath)
|
||||
}
|
||||
|
||||
helmChart, ok := helmSourceToChart[workloadPath]
|
||||
if !ok {
|
||||
return nil, nil, nil, fmt.Errorf("helmChart not found for workload %s", workloadPath)
|
||||
}
|
||||
|
||||
templatesNodes, ok := helmSourceToNodes[workloadPath]
|
||||
if !ok {
|
||||
return nil, nil, nil, fmt.Errorf("templatesNodes not found for workload %s", workloadPath)
|
||||
return nil, nil, fmt.Errorf("helmChart not found for workload %s", workloadPath)
|
||||
}
|
||||
|
||||
workloadSource := getWorkloadSourceHelmChart(repoRoot, helmPath, gitRepo, helmChart)
|
||||
|
||||
workloadIDToSource := make(map[string]reporthandling.Source, 1)
|
||||
workloadIDToNodes := make(map[string]cautils.MappingNodes, 1)
|
||||
workloadIDToSource[wlSource[0].GetID()] = workloadSource
|
||||
workloadIDToNodes[wlSource[0].GetID()] = templatesNodes
|
||||
|
||||
var workloads []workloadinterface.IMetadata
|
||||
workloads = append(workloads, wlSource...)
|
||||
|
||||
return workloadIDToSource, workloads, workloadIDToNodes, nil
|
||||
return workloadIDToSource, workloads, nil
|
||||
|
||||
}
|
||||
|
||||
@@ -185,9 +172,8 @@ func getWorkloadSourceHelmChart(repoRoot string, source string, gitRepo *cautils
|
||||
}
|
||||
}
|
||||
|
||||
func getResourcesFromPath(ctx context.Context, path string) (map[string]reporthandling.Source, []workloadinterface.IMetadata, map[string]cautils.MappingNodes, error) {
|
||||
func getResourcesFromPath(ctx context.Context, path string) (map[string]reporthandling.Source, []workloadinterface.IMetadata, error) {
|
||||
workloadIDToSource := make(map[string]reporthandling.Source)
|
||||
workloadIDToNodes := make(map[string]cautils.MappingNodes)
|
||||
var workloads []workloadinterface.IMetadata
|
||||
|
||||
clonedRepo := cautils.GetClonedPath(path)
|
||||
@@ -274,14 +260,10 @@ func getResourcesFromPath(ctx context.Context, path string) (map[string]reportha
|
||||
}
|
||||
|
||||
// load resources from helm charts
|
||||
helmSourceToWorkloads, helmSourceToChart, helmSourceToNodes := cautils.LoadResourcesFromHelmCharts(ctx, path)
|
||||
helmSourceToWorkloads, helmSourceToChart := cautils.LoadResourcesFromHelmCharts(ctx, path)
|
||||
for source, ws := range helmSourceToWorkloads {
|
||||
workloads = append(workloads, ws...)
|
||||
helmChart := helmSourceToChart[source]
|
||||
var templatesNodes cautils.MappingNodes
|
||||
if nodes, ok := helmSourceToNodes[source]; ok {
|
||||
templatesNodes = nodes
|
||||
}
|
||||
|
||||
if clonedRepo != "" && gitRepo != nil {
|
||||
url, err := gitRepo.GetRemoteUrl()
|
||||
@@ -292,14 +274,12 @@ func getResourcesFromPath(ctx context.Context, path string) (map[string]reportha
|
||||
helmChart.Path = strings.TrimSuffix(url, ".git")
|
||||
repoRoot = ""
|
||||
source = strings.TrimPrefix(source, fmt.Sprintf("%s/", clonedRepo))
|
||||
templatesNodes.TemplateFileName = source
|
||||
}
|
||||
|
||||
workloadSource := getWorkloadSourceHelmChart(repoRoot, source, gitRepo, helmChart)
|
||||
|
||||
for i := range ws {
|
||||
workloadIDToSource[ws[i].GetID()] = workloadSource
|
||||
workloadIDToNodes[ws[i].GetID()] = templatesNodes
|
||||
}
|
||||
}
|
||||
|
||||
@@ -346,7 +326,7 @@ func getResourcesFromPath(ctx context.Context, path string) (map[string]reportha
|
||||
}
|
||||
}
|
||||
|
||||
return workloadIDToSource, workloads, workloadIDToNodes, nil
|
||||
return workloadIDToSource, workloads, nil
|
||||
}
|
||||
|
||||
func extractGitRepo(path string) (string, *cautils.LocalGitRepository) {
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
|
||||
"github.com/kubescape/opa-utils/reporthandling/apis"
|
||||
helpersv1 "github.com/kubescape/opa-utils/reporthandling/helpers/v1"
|
||||
reportv2 "github.com/kubescape/opa-utils/reporthandling/v2"
|
||||
@@ -100,12 +99,12 @@ func Test_CollectResources(t *testing.T) {
|
||||
}
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
CollectResources(context.TODO(), resourceHandler, []cautils.PolicyIdentifier{}, objSession, cautils.NewProgressHandler(""), &cautils.ScanInfo{})
|
||||
CollectResources(context.TODO(), resourceHandler, objSession, &cautils.ScanInfo{})
|
||||
}, "Cluster named .*eks.* without a cloud config panics on cluster scan !")
|
||||
|
||||
assert.NotPanics(t, func() {
|
||||
objSession.Metadata.ScanMetadata.ScanningTarget = reportv2.File
|
||||
CollectResources(context.TODO(), resourceHandler, []cautils.PolicyIdentifier{}, objSession, cautils.NewProgressHandler(""), &cautils.ScanInfo{})
|
||||
CollectResources(context.TODO(), resourceHandler, objSession, &cautils.ScanInfo{})
|
||||
}, "Cluster named .*eks.* without a cloud config panics on non-cluster scan !")
|
||||
|
||||
}
|
||||
|
||||
@@ -4,19 +4,18 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
cloudsupportv1 "github.com/kubescape/k8s-interface/cloudsupport/v1"
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/opaprocessor"
|
||||
"github.com/kubescape/opa-utils/reporthandling/apis"
|
||||
helpersv1 "github.com/kubescape/opa-utils/reporthandling/helpers/v1"
|
||||
reportv2 "github.com/kubescape/opa-utils/reporthandling/v2"
|
||||
"go.opentelemetry.io/otel"
|
||||
)
|
||||
|
||||
func CollectResources(ctx context.Context, rsrcHandler IResourceHandler, policyIdentifier []cautils.PolicyIdentifier, opaSessionObj *cautils.OPASessionObj, progressListener opaprocessor.IJobProgressNotificationClient, scanInfo *cautils.ScanInfo) error {
|
||||
func CollectResources(ctx context.Context, rsrcHandler IResourceHandler, opaSessionObj *cautils.OPASessionObj, scanInfo *cautils.ScanInfo) error {
|
||||
ctx, span := otel.Tracer("").Start(ctx, "resourcehandler.CollectResources")
|
||||
defer span.End()
|
||||
opaSessionObj.Report.ClusterAPIServerInfo = rsrcHandler.GetClusterAPIServerInfo(ctx)
|
||||
@@ -26,7 +25,7 @@ func CollectResources(ctx context.Context, rsrcHandler IResourceHandler, policyI
|
||||
setCloudMetadata(opaSessionObj, rsrcHandler.GetCloudProvider())
|
||||
}
|
||||
|
||||
resourcesMap, allResources, externalResources, excludedRulesMap, err := rsrcHandler.GetResources(ctx, opaSessionObj, progressListener, scanInfo)
|
||||
resourcesMap, allResources, externalResources, excludedRulesMap, err := rsrcHandler.GetResources(ctx, opaSessionObj, scanInfo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -5,12 +5,11 @@ import (
|
||||
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/opaprocessor"
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
)
|
||||
|
||||
type IResourceHandler interface {
|
||||
GetResources(context.Context, *cautils.OPASessionObj, opaprocessor.IJobProgressNotificationClient, *cautils.ScanInfo) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.ExternalResources, map[string]bool, error)
|
||||
GetResources(context.Context, *cautils.OPASessionObj, *cautils.ScanInfo) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.ExternalResources, map[string]bool, error)
|
||||
GetClusterAPIServerInfo(ctx context.Context) *version.Info
|
||||
GetCloudProvider() string
|
||||
}
|
||||
|
||||
@@ -5,27 +5,26 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/metrics"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/hostsensorutils"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/opaprocessor"
|
||||
"github.com/kubescape/opa-utils/objectsenvelopes"
|
||||
"github.com/kubescape/opa-utils/reporthandling/apis"
|
||||
|
||||
"github.com/kubescape/k8s-interface/cloudsupport"
|
||||
cloudapis "github.com/kubescape/k8s-interface/cloudsupport/apis"
|
||||
cloudv1 "github.com/kubescape/k8s-interface/cloudsupport/v1"
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/metrics"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/hostsensorutils"
|
||||
"github.com/kubescape/opa-utils/objectsenvelopes"
|
||||
"github.com/kubescape/opa-utils/reporthandling/apis"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
k8slabels "k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
"k8s.io/client-go/tools/pager"
|
||||
)
|
||||
|
||||
type cloudResourceGetter func(string, string) (workloadinterface.IMetadata, error)
|
||||
@@ -60,7 +59,7 @@ func NewK8sResourceHandler(k8s *k8sinterface.KubernetesApi, hostSensorHandler ho
|
||||
return k8sHandler
|
||||
}
|
||||
|
||||
func (k8sHandler *K8sResourceHandler) GetResources(ctx context.Context, sessionObj *cautils.OPASessionObj, progressListener opaprocessor.IJobProgressNotificationClient, scanInfo *cautils.ScanInfo) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.ExternalResources, map[string]bool, error) {
|
||||
func (k8sHandler *K8sResourceHandler) GetResources(ctx context.Context, sessionObj *cautils.OPASessionObj, scanInfo *cautils.ScanInfo) (cautils.K8SResources, map[string]workloadinterface.IMetadata, cautils.ExternalResources, map[string]bool, error) {
|
||||
logger.L().Start("Accessing Kubernetes objects...")
|
||||
var err error
|
||||
|
||||
@@ -145,7 +144,7 @@ func (k8sHandler *K8sResourceHandler) GetResources(ctx context.Context, sessionO
|
||||
|
||||
// check that controls use cloud resources
|
||||
if len(cloudResources) > 0 {
|
||||
err := k8sHandler.collectCloudResources(ctx, sessionObj, allResources, ksResourceMap, cloudResources, progressListener)
|
||||
err := k8sHandler.collectCloudResources(ctx, sessionObj, allResources, ksResourceMap, cloudResources)
|
||||
if err != nil {
|
||||
cautils.SetInfoMapForResources(err.Error(), cloudResources, sessionObj.InfoMap)
|
||||
logger.L().Debug("failed to collect cloud data", helpers.Error(err))
|
||||
@@ -173,9 +172,9 @@ func (k8sHandler *K8sResourceHandler) findScanObjectResource(resource *objectsen
|
||||
}
|
||||
|
||||
if resource.GetApiVersion() != "" {
|
||||
group, version := k8sinterface.SplitApiVersion(resource.GetApiVersion())
|
||||
gvr.Group = group
|
||||
gvr.Version = version
|
||||
g, v := k8sinterface.SplitApiVersion(resource.GetApiVersion())
|
||||
gvr.Group = g
|
||||
gvr.Version = v
|
||||
}
|
||||
|
||||
fieldSelectors := getNameFieldSelectorString(resource.GetName(), FieldSelectorsEqualsOperator)
|
||||
@@ -208,7 +207,7 @@ func (k8sHandler *K8sResourceHandler) findScanObjectResource(resource *objectsen
|
||||
return wl, nil
|
||||
}
|
||||
|
||||
func (k8sHandler *K8sResourceHandler) collectCloudResources(ctx context.Context, sessionObj *cautils.OPASessionObj, allResources map[string]workloadinterface.IMetadata, externalResourceMap cautils.ExternalResources, cloudResources []string, progressListener opaprocessor.IJobProgressNotificationClient) error {
|
||||
func (k8sHandler *K8sResourceHandler) collectCloudResources(ctx context.Context, sessionObj *cautils.OPASessionObj, allResources map[string]workloadinterface.IMetadata, externalResourceMap cautils.ExternalResources, cloudResources []string) error {
|
||||
|
||||
if k8sHandler.cloudProvider == "" {
|
||||
return fmt.Errorf("failed to get cloud provider, cluster: %s", k8sHandler.clusterName)
|
||||
@@ -356,7 +355,7 @@ func (k8sHandler *K8sResourceHandler) pullResources(queryableResources Queryable
|
||||
}
|
||||
|
||||
func (k8sHandler *K8sResourceHandler) pullSingleResource(resource *schema.GroupVersionResource, labels map[string]string, fields string, fieldSelector IFieldSelector) ([]unstructured.Unstructured, error) {
|
||||
resourceList := []unstructured.Unstructured{}
|
||||
var resourceList []unstructured.Unstructured
|
||||
// set labels
|
||||
listOptions := metav1.ListOptions{}
|
||||
fieldSelectors := fieldSelector.GetNamespacesSelectors(resource)
|
||||
@@ -376,30 +375,30 @@ func (k8sHandler *K8sResourceHandler) pullSingleResource(resource *schema.GroupV
|
||||
clientResource := k8sHandler.k8s.DynamicClient.Resource(*resource)
|
||||
|
||||
// list resources
|
||||
result, err := clientResource.List(context.Background(), listOptions)
|
||||
if err != nil || result == nil {
|
||||
return nil, fmt.Errorf("failed to get resource: %v, labelSelector: %v, fieldSelector: %v, reason: %v", resource, listOptions.LabelSelector, listOptions.FieldSelector, err)
|
||||
lenBefore := len(resourceList)
|
||||
if err := pager.New(func(ctx context.Context, opts metav1.ListOptions) (runtime.Object, error) {
|
||||
return clientResource.List(ctx, opts)
|
||||
}).EachListItem(context.Background(), listOptions, func(obj runtime.Object) error {
|
||||
uObject := obj.(*unstructured.Unstructured)
|
||||
if k8sinterface.IsTypeWorkload(uObject.Object) && k8sinterface.WorkloadHasParent(workloadinterface.NewWorkloadObj(uObject.Object)) {
|
||||
logger.L().Debug("Skipping resource with parent", helpers.String("resource", resource.String()), helpers.String("namespace", uObject.GetNamespace()), helpers.String("name", uObject.GetName()))
|
||||
return nil
|
||||
}
|
||||
resourceList = append(resourceList, *obj.(*unstructured.Unstructured))
|
||||
return nil
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("failed to get resource: %v, labelSelector: %v, fieldSelector: %v, reason: %w", resource, listOptions.LabelSelector, listOptions.FieldSelector, err)
|
||||
}
|
||||
|
||||
resourceList = append(resourceList, result.Items...)
|
||||
|
||||
logger.L().Debug("Pulled resources", helpers.String("resource", resource.String()), helpers.String("fieldSelector", listOptions.FieldSelector), helpers.String("labelSelector", listOptions.LabelSelector), helpers.Int("count", len(resourceList)-lenBefore))
|
||||
}
|
||||
|
||||
return resourceList, nil
|
||||
|
||||
}
|
||||
func ConvertMapListToMeta(resourceMap []map[string]interface{}) []workloadinterface.IMetadata {
|
||||
workloads := []workloadinterface.IMetadata{}
|
||||
var workloads []workloadinterface.IMetadata
|
||||
for i := range resourceMap {
|
||||
r := resourceMap[i]
|
||||
|
||||
// skip workloads with parents. e.g. Pod with a ReplicaSet ownerReference. This will not skip resources with CRDs asa parents
|
||||
if k8sinterface.IsTypeWorkload(r) {
|
||||
if k8sinterface.WorkloadHasParent(workloadinterface.NewWorkloadObj(r)) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
if w := objectsenvelopes.NewObject(r); w != nil {
|
||||
workloads = append(workloads, w)
|
||||
}
|
||||
@@ -415,8 +414,8 @@ func (k8sHandler *K8sResourceHandler) collectHostResources(ctx context.Context,
|
||||
}
|
||||
|
||||
for rscIdx := range hostResources {
|
||||
group, version := getGroupNVersion(hostResources[rscIdx].GetApiVersion())
|
||||
groupResource := k8sinterface.JoinResourceTriplets(group, version, hostResources[rscIdx].GetKind())
|
||||
g, v := getGroupNVersion(hostResources[rscIdx].GetApiVersion())
|
||||
groupResource := k8sinterface.JoinResourceTriplets(g, v, hostResources[rscIdx].GetKind())
|
||||
allResources[hostResources[rscIdx].GetID()] = &hostResources[rscIdx]
|
||||
|
||||
grpResourceList, ok := externalResourceMap[groupResource]
|
||||
|
||||
@@ -4,13 +4,12 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/opa-utils/objectsenvelopes"
|
||||
"github.com/kubescape/opa-utils/reporthandling"
|
||||
"k8s.io/utils/strings/slices"
|
||||
|
||||
"github.com/kubescape/k8s-interface/k8sinterface"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
package resourcehandler
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/opa-utils/objectsenvelopes"
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestSsEmptyImgVulns(t *testing.T) {
|
||||
|
||||
@@ -229,8 +229,14 @@ func (g *GitHubRepository) getFilesFromTree(filesExtensions []string) []string {
|
||||
return []string{}
|
||||
}
|
||||
}
|
||||
|
||||
basePath := g.path
|
||||
if basePath != "" && !strings.HasSuffix(basePath, "/") {
|
||||
basePath += "/"
|
||||
}
|
||||
|
||||
for _, path := range g.tree.InnerTrees {
|
||||
if g.path != "" && !strings.HasPrefix(path.Path, g.path) {
|
||||
if basePath != "" && !strings.HasPrefix(path.Path, basePath) {
|
||||
continue
|
||||
}
|
||||
if slices.Contains(filesExtensions, getFileExtension(path.Path)) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package resourcehandler
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
@@ -13,6 +14,27 @@ var (
|
||||
// urlD = "https://raw.githubusercontent.com/kubescape/kubescape/master/examples/online-boutique/adservice.yaml"
|
||||
)
|
||||
|
||||
var mockTree = tree{
|
||||
InnerTrees: []innerTree{
|
||||
{Path: "charts/fluent-bit/values.yaml"},
|
||||
{Path: "charts/fluent-bit/templates/configmap.yaml"},
|
||||
{Path: "charts/other-chart/templates/deployment.yaml"},
|
||||
{Path: "README.md"},
|
||||
},
|
||||
}
|
||||
|
||||
func newMockGitHubRepository(path string, isFile bool) *GitHubRepository {
|
||||
return &GitHubRepository{
|
||||
host: "github.com",
|
||||
owner: "grafana",
|
||||
repo: "helm-charts",
|
||||
branch: "main",
|
||||
path: path,
|
||||
isFile: isFile,
|
||||
tree: mockTree,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
TODO: tests were commented out due to actual http calls ; http calls should be mocked.
|
||||
@@ -143,3 +165,60 @@ func TestGithubParse(t *testing.T) {
|
||||
assert.False(t, gh.isFile)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetFilesFromTree(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
repo *GitHubRepository
|
||||
extensions []string
|
||||
expectedResults []string
|
||||
}{
|
||||
{
|
||||
name: "Scan entire repo for YAML files",
|
||||
repo: newMockGitHubRepository("", false),
|
||||
extensions: []string{"yaml", "yml"},
|
||||
expectedResults: []string{
|
||||
"https://raw.githubusercontent.com/grafana/helm-charts/main/charts/fluent-bit/values.yaml",
|
||||
"https://raw.githubusercontent.com/grafana/helm-charts/main/charts/fluent-bit/templates/configmap.yaml",
|
||||
"https://raw.githubusercontent.com/grafana/helm-charts/main/charts/other-chart/templates/deployment.yaml",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Scan specific folder (fluent-bit) for YAML files",
|
||||
repo: newMockGitHubRepository("charts/fluent-bit", false),
|
||||
extensions: []string{"yaml", "yml"},
|
||||
expectedResults: []string{
|
||||
"https://raw.githubusercontent.com/grafana/helm-charts/main/charts/fluent-bit/values.yaml",
|
||||
"https://raw.githubusercontent.com/grafana/helm-charts/main/charts/fluent-bit/templates/configmap.yaml",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Scan root with non-matching extension (JSON)",
|
||||
repo: newMockGitHubRepository("", false),
|
||||
extensions: []string{"json"},
|
||||
expectedResults: []string{},
|
||||
},
|
||||
{
|
||||
name: "Scan specific file",
|
||||
repo: newMockGitHubRepository("charts/fluent-bit/values.yaml", true),
|
||||
extensions: []string{"yaml"},
|
||||
expectedResults: []string{
|
||||
"https://raw.githubusercontent.com/grafana/helm-charts/main/charts/fluent-bit/values.yaml",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := tt.repo.getFilesFromTree(tt.extensions)
|
||||
|
||||
if len(got) == 0 && len(tt.expectedResults) == 0 {
|
||||
return // both are empty, so this test case passes
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(got, tt.expectedResults) {
|
||||
t.Errorf("getFilesFromTree() = %v, want %v", got, tt.expectedResults)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
@@ -60,7 +60,7 @@ func NewResourcesPrioritizationHandler(ctx context.Context, attackTracksGetter g
|
||||
// Store attack tracks in cache
|
||||
cache := getter.GetDefaultPath(cautils.LocalAttackTracksFilename)
|
||||
if err := getter.SaveInFile(tracks, cache); err != nil {
|
||||
logger.L().Ctx(ctx).Warning("failed to cache file", helpers.String("file", cache), helpers.Error(err))
|
||||
logger.L().Ctx(ctx).Warning("failed to cache attack track", helpers.String("file", cache), helpers.Error(err))
|
||||
}
|
||||
|
||||
return handler, nil
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/mikefarah/yq/v4/pkg/yqlib"
|
||||
|
||||
"gopkg.in/op/go-logging.v1"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
)
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer"
|
||||
)
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer"
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
|
||||
"github.com/kubescape/kubescape/v3/internal/testutils"
|
||||
"github.com/kubescape/opa-utils/reporthandling/results/v1/reportsummary"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer"
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/anchore/clio"
|
||||
"github.com/anchore/grype/grype/presenter"
|
||||
"github.com/anchore/grype/grype/presenter/models"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer"
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
|
||||
@@ -10,17 +10,16 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/johnfercher/maroto/pkg/color"
|
||||
"github.com/johnfercher/maroto/pkg/consts"
|
||||
"github.com/johnfercher/maroto/pkg/pdf"
|
||||
"github.com/johnfercher/maroto/pkg/props"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer/v2/prettyprinter/tableprinter/utils"
|
||||
"github.com/kubescape/opa-utils/reporthandling/results/v1/reportsummary"
|
||||
|
||||
"github.com/johnfercher/maroto/pkg/color"
|
||||
"github.com/johnfercher/maroto/pkg/consts"
|
||||
"github.com/johnfercher/maroto/pkg/pdf"
|
||||
"github.com/johnfercher/maroto/pkg/props"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
"github.com/anchore/grype/grype/presenter/models"
|
||||
"github.com/enescakir/emoji"
|
||||
"github.com/jwalton/gchalk"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"os"
|
||||
|
||||
"github.com/anchore/grype/grype/presenter/models"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
|
||||
"github.com/anchore/grype/grype/presenter"
|
||||
"github.com/anchore/grype/grype/presenter/models"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/fixhandler"
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/armosec/armoapi-go/apis"
|
||||
client "github.com/kubescape/backend/pkg/client/v1"
|
||||
v1 "github.com/kubescape/backend/pkg/server/v1"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/k8s-interface/workloadinterface"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
@@ -162,7 +162,11 @@ func (report *ReportEventReceiver) setResults(reportObj *reporthandlingv2.Postur
|
||||
|
||||
r, err := json.Marshal(v)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unmarshal resource '%s', reason: %v", v.GetResourceID(), err)
|
||||
logger.L().Error("failed to marshal resource to JSON - skipping",
|
||||
helpers.Error(err),
|
||||
helpers.String("file", resource.GetSource().RelativePath),
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
if *counter+len(r) >= MAX_REPORT_SIZE && len(reportObj.Results) > 0 {
|
||||
@@ -204,7 +208,11 @@ func (report *ReportEventReceiver) setResources(reportObj *reporthandlingv2.Post
|
||||
}
|
||||
r, err := json.Marshal(resource)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to unmarshal resource '%s', reason: %v", resourceID, err)
|
||||
logger.L().Error("failed to marshal resource to JSON - skipping",
|
||||
helpers.Error(err),
|
||||
helpers.String("file", resource.GetSource().RelativePath),
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
if *counter+len(r) >= MAX_REPORT_SIZE && len(reportObj.Resources) > 0 {
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
"testing"
|
||||
|
||||
v1 "github.com/kubescape/backend/pkg/client/v1"
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/prettylogger"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils/getter"
|
||||
|
||||
@@ -5,7 +5,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
logger "github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/kubescape/v3/core/pkg/resultshandling/printer"
|
||||
@@ -54,7 +54,7 @@ func (rh *ResultsHandler) SetData(data *cautils.OPASessionObj) {
|
||||
rh.ScanData = data
|
||||
}
|
||||
|
||||
// GetPrinter returns all printers
|
||||
// GetPrinters returns all printers
|
||||
func (rh *ResultsHandler) GetPrinters() []printer.IPrinter {
|
||||
return rh.PrinterObjs
|
||||
}
|
||||
|
||||
@@ -3,9 +3,8 @@ package score
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/kubescape/opa-utils/score"
|
||||
|
||||
"github.com/kubescape/kubescape/v3/core/cautils"
|
||||
"github.com/kubescape/opa-utils/score"
|
||||
)
|
||||
|
||||
/*
|
||||
|
||||
@@ -6,7 +6,7 @@ The best way to get started with Kubescape is to download it to the machine you
|
||||
|
||||
## Install Kubescape
|
||||
|
||||
```sh
|
||||
```bash
|
||||
curl -s https://raw.githubusercontent.com/kubescape/kubescape/master/install.sh | /bin/bash
|
||||
```
|
||||
|
||||
@@ -16,175 +16,255 @@ You can also check [other installation methods](installation.md)
|
||||
|
||||
## Run your first scan
|
||||
|
||||
```sh
|
||||
kubescape scan --verbose
|
||||
```bash
|
||||
kubescape scan
|
||||
```
|
||||
|
||||
You will see output like this:
|
||||
|
||||
<img src="img/summary.png">
|
||||
```bash
|
||||
Kubescape security posture overview for cluster: minikube
|
||||
|
||||
## Usage
|
||||
In this overview, Kubescape shows you a summary of your cluster security posture, including the number of users who can perform administrative actions. For each result greater than 0, you should evaluate its need, and then define an exception to allow it. This baseline can be used to detect drift in future.
|
||||
|
||||
_Some documentation on using Kubescape is yet to move here from the [ARMO Platform docs](https://hub.armosec.io/docs?utm_source=github&utm_medium=repository)_.
|
||||
Control plane
|
||||
┌────┬─────────────────────────────────────┬────────────────────────────────────┐
|
||||
│ │ Control Name │ Docs │
|
||||
├────┼─────────────────────────────────────┼────────────────────────────────────┤
|
||||
│ ✅ │ API server insecure port is enabled │ https://hub.armosec.io/docs/c-0005 │
|
||||
│ ❌ │ Anonymous access enabled │ https://hub.armosec.io/docs/c-0262 │
|
||||
│ ❌ │ Audit logs enabled │ https://hub.armosec.io/docs/c-0067 │
|
||||
│ ✅ │ RBAC enabled │ https://hub.armosec.io/docs/c-0088 │
|
||||
│ ❌ │ Secret/etcd encryption enabled │ https://hub.armosec.io/docs/c-0066 │
|
||||
└────┴─────────────────────────────────────┴────────────────────────────────────┘
|
||||
|
||||
Access control
|
||||
┌─────────────────────────────────────────────────┬───────────┬────────────────────────────────────┐
|
||||
│ Control Name │ Resources │ View Details │
|
||||
├─────────────────────────────────────────────────┼───────────┼────────────────────────────────────┤
|
||||
│ Cluster-admin binding │ 1 │ $ kubescape scan control C-0035 -v │
|
||||
│ Data Destruction │ 6 │ $ kubescape scan control C-0007 -v │
|
||||
│ Exec into container │ 1 │ $ kubescape scan control C-0002 -v │
|
||||
│ List Kubernetes secrets │ 6 │ $ kubescape scan control C-0015 -v │
|
||||
│ Minimize access to create pods │ 2 │ $ kubescape scan control C-0188 -v │
|
||||
│ Minimize wildcard use in Roles and ClusterRoles │ 1 │ $ kubescape scan control C-0187 -v │
|
||||
│ Portforwarding privileges │ 1 │ $ kubescape scan control C-0063 -v │
|
||||
│ Validate admission controller (mutating) │ 0 │ $ kubescape scan control C-0039 -v │
|
||||
│ Validate admission controller (validating) │ 0 │ $ kubescape scan control C-0036 -v │
|
||||
└─────────────────────────────────────────────────┴───────────┴────────────────────────────────────┘
|
||||
|
||||
Secrets
|
||||
┌─────────────────────────────────────────────────┬───────────┬────────────────────────────────────┐
|
||||
│ Control Name │ Resources │ View Details │
|
||||
├─────────────────────────────────────────────────┼───────────┼────────────────────────────────────┤
|
||||
│ Applications credentials in configuration files │ 1 │ $ kubescape scan control C-0012 -v │
|
||||
└─────────────────────────────────────────────────┴───────────┴────────────────────────────────────┘
|
||||
|
||||
Network
|
||||
┌────────────────────────┬───────────┬────────────────────────────────────┐
|
||||
│ Control Name │ Resources │ View Details │
|
||||
├────────────────────────┼───────────┼────────────────────────────────────┤
|
||||
│ Missing network policy │ 13 │ $ kubescape scan control C-0260 -v │
|
||||
└────────────────────────┴───────────┴────────────────────────────────────┘
|
||||
|
||||
Workload
|
||||
┌─────────────────────────┬───────────┬────────────────────────────────────┐
|
||||
│ Control Name │ Resources │ View Details │
|
||||
├─────────────────────────┼───────────┼────────────────────────────────────┤
|
||||
│ Host PID/IPC privileges │ 2 │ $ kubescape scan control C-0038 -v │
|
||||
│ HostNetwork access │ 1 │ $ kubescape scan control C-0041 -v │
|
||||
│ HostPath mount │ 1 │ $ kubescape scan control C-0048 -v │
|
||||
│ Non-root containers │ 6 │ $ kubescape scan control C-0013 -v │
|
||||
│ Privileged container │ 1 │ $ kubescape scan control C-0057 -v │
|
||||
└─────────────────────────┴───────────┴────────────────────────────────────┘
|
||||
|
||||
Highest-stake workloads
|
||||
────────────────────────
|
||||
High-stakes workloads are defined as those which Kubescape estimates would have the highest impact if they were to be exploited.
|
||||
|
||||
1. namespace: gadget, name: gadget, kind: DaemonSet
|
||||
'$ kubescape scan workload DaemonSet/gadget --namespace gadget'
|
||||
2. namespace: kafka, name: my-cluster-kafka-0, kind: Pod
|
||||
'$ kubescape scan workload Pod/my-cluster-kafka-0 --namespace kafka'
|
||||
3. namespace: kafka, name: my-cluster-zookeeper-0, kind: Pod
|
||||
'$ kubescape scan workload Pod/my-cluster-zookeeper-0 --namespace kafka'
|
||||
|
||||
Compliance Score
|
||||
────────────────
|
||||
The compliance score is calculated by multiplying control failures by the number of failures against supported compliance frameworks. Remediate controls, or configure your cluster baseline with exceptions, to improve this score.
|
||||
|
||||
* MITRE: 77.39%
|
||||
* NSA: 69.97%
|
||||
|
||||
View a full compliance report by running '$ kubescape scan framework nsa' or '$ kubescape scan framework mitre'
|
||||
|
||||
What now?
|
||||
─────────
|
||||
* Run one of the suggested commands to learn more about a failed control failure
|
||||
* Scan a workload with '$ kubescape scan workload' to see vulnerability information
|
||||
* Install Kubescape in your cluster for continuous monitoring and a full vulnerability report: https://github.com/kubescape/helm-charts/tree/main/charts/kubescape-operator
|
||||
|
||||
```
|
||||
|
||||
# Usage
|
||||
|
||||
Capabilities
|
||||
* Scan Kubernetes clusters for misconfigurations
|
||||
* Scan Kubernetes YAML files/Helm charts for misconfigurations
|
||||
* Scan container images for vulnerabilities
|
||||
|
||||
## Misconfigurations Scanning
|
||||
Scan Kubernetes clusters, YAML files, Helm charts for misconfigurations.
|
||||
Kubescape will highlight the misconfigurations and provide remediation steps.
|
||||
The misconfigurations are based on multiple frameworks (including [NSA-CISA](https://www.armosec.io/blog/kubernetes-hardening-guidance-summary-by-armo/?utm_source=github&utm_medium=repository), [MITRE ATT&CK®](https://www.microsoft.com/security/blog/2021/03/23/secure-containerized-environments-with-updated-threat-matrix-for-kubernetes/) and the [CIS Benchmark](https://www.armosec.io/blog/cis-kubernetes-benchmark-framework-scanning-tools-comparison/?utm_source=github&utm_medium=repository)).
|
||||
|
||||
### Examples
|
||||
|
||||
* Scan a running Kubernetes cluster:
|
||||
#### Scan a running Kubernetes cluster:
|
||||
|
||||
```sh
|
||||
kubescape scan --verbose
|
||||
```bash
|
||||
kubescape scan
|
||||
```
|
||||
|
||||
> **Note**
|
||||
> [Read more about host scanning](https://hub.armosec.io/docs/host-sensor?utm_source=github&utm_medium=repository).
|
||||
|
||||
#### Scan NSA framework
|
||||
Scan a running Kubernetes cluster with the [NSA framework](https://www.nsa.gov/Press-Room/News-Highlights/Article/Article/2716980/nsa-cisa-release-kubernetes-hardening-guidance/):
|
||||
|
||||
```bash
|
||||
kubescape scan framework nsa
|
||||
```
|
||||
|
||||
#### Scan MITRE framework
|
||||
Scan a running Kubernetes cluster with the [MITRE ATT&CK® framework](https://www.microsoft.com/security/blog/2021/03/23/secure-containerized-environments-with-updated-threat-matrix-for-kubernetes/):
|
||||
|
||||
```bash
|
||||
kubescape scan framework mitre
|
||||
```
|
||||
|
||||
#### Scan a control
|
||||
Scan for a specific control, using the control name or control ID. [See the list of controls](https://hub.armosec.io/docs/controls?utm_source=github&utm_medium=repository).
|
||||
|
||||
```bash
|
||||
kubescape scan control c-0005 -v
|
||||
```
|
||||
|
||||
#### Use an alternative kubeconfig file
|
||||
|
||||
```bash
|
||||
kubescape scan --kubeconfig cluster.conf
|
||||
```
|
||||
|
||||
#### Scan specific namespaces
|
||||
|
||||
```bash
|
||||
kubescape scan --include-namespaces development,staging,production
|
||||
```
|
||||
|
||||
#### Exclude certain namespaces
|
||||
|
||||
```bash
|
||||
kubescape scan --exclude-namespaces kube-system,kube-public
|
||||
```
|
||||
|
||||
#### Scan local YAML files
|
||||
```sh
|
||||
kubescape scan /path/to/directory-or-directory
|
||||
```
|
||||
|
||||
Take a look at the [example](https://youtu.be/Ox6DaR7_4ZI).
|
||||
|
||||
#### Scan git repository
|
||||
Scan Kubernetes manifest files from a Git repository:
|
||||
|
||||
```bash
|
||||
kubescape scan https://github.com/kubescape/kubescape
|
||||
```
|
||||
|
||||
#### Scan with exceptions
|
||||
|
||||
```bash
|
||||
kubescape scan --exceptions examples/exceptions/exclude-kube-namespaces.json
|
||||
```
|
||||
|
||||
Objects with exceptions will be presented as `exclude` and not `fail`.
|
||||
|
||||
[See more examples about exceptions.](/examples/exceptions/README.md)
|
||||
|
||||
#### Scan Helm charts
|
||||
|
||||
```bash
|
||||
kubescape scan </path/to/directory>
|
||||
```
|
||||
|
||||
> **Note**
|
||||
> Kubescape will load the default VALUES file.
|
||||
|
||||
#### Scan a Kustomize directory
|
||||
|
||||
```bash
|
||||
kubescape scan </path/to/directory>
|
||||
```
|
||||
|
||||
> **Note**
|
||||
> Kubescape will generate Kubernetes YAML objects using a `kustomize` file and scan them for security.
|
||||
|
||||
#### Trigger in cluster components for scanning your cluster
|
||||
|
||||
If the [kubescape-operator](https://github.com/kubescape/helm-charts/tree/main/charts/kubescape-operator#readme) is installed in your cluster, you can trigger scanning of the in cluster components from the kubescape CLI.
|
||||
|
||||
Trigger configuration scanning:
|
||||
```bash
|
||||
kubescape operator scan configurations
|
||||
```
|
||||
|
||||
Trigger vulnerabilities scanning:
|
||||
```bash
|
||||
kubescape operator scan vulnerabilities
|
||||
```
|
||||
|
||||
#### Compliance Score
|
||||
|
||||
We offer two important metrics to assess compliance:
|
||||
|
||||
- Control Compliance Score: This score measures the compliance of individual controls within a framework. It is calculated by evaluating the ratio of resources that passed to the total number of resources evaluated against that control.
|
||||
```bash
|
||||
kubescape scan --compliance-threshold <SCORE_VALUE[float32]>
|
||||
```
|
||||
|
||||
> **Note**
|
||||
> [Read more about host scanning](https://hub.armosec.io/docs/host-sensor?utm_source=github&utm_medium=repository).
|
||||
|
||||
* Scan a running Kubernetes cluster with the [NSA framework](https://www.nsa.gov/Press-Room/News-Highlights/Article/Article/2716980/nsa-cisa-release-kubernetes-hardening-guidance/):
|
||||
|
||||
```sh
|
||||
kubescape scan framework nsa
|
||||
- Framework Compliance Score: This score provides an overall assessment of your cluster's compliance with a specific framework. It is calculated by averaging the Control Compliance Scores of all controls within the framework.
|
||||
```bash
|
||||
kubescape scan framework <FRAMEWORK_NAME> --compliance-threshold <SCORE_VALUE[float32]>
|
||||
```
|
||||
|
||||
* Scan a running Kubernetes cluster with the [MITRE ATT&CK® framework](https://www.microsoft.com/security/blog/2021/03/23/secure-containerized-environments-with-updated-threat-matrix-for-kubernetes/):
|
||||
|
||||
```sh
|
||||
kubescape scan framework mitre
|
||||
```
|
||||
|
||||
* Scan for a specific control, using the control name or control ID. [See the list of controls](https://hub.armosec.io/docs/controls?utm_source=github&utm_medium=repository).
|
||||
|
||||
```sh
|
||||
kubescape scan control "Privileged container"
|
||||
```
|
||||
|
||||
* Use an alternative kubeconfig file:
|
||||
|
||||
```sh
|
||||
kubescape scan --kubeconfig cluster.conf
|
||||
```
|
||||
|
||||
* Scan specific namespaces:
|
||||
|
||||
```sh
|
||||
kubescape scan --include-namespaces development,staging,production
|
||||
```
|
||||
|
||||
* Exclude certain namespaces:
|
||||
|
||||
```sh
|
||||
kubescape scan --exclude-namespaces kube-system,kube-public
|
||||
```
|
||||
|
||||
* Scan local YAML/JSON files before deploying:
|
||||
```sh
|
||||
kubescape scan *.yaml
|
||||
```
|
||||
|
||||
[Take a look at the demonstration](https://youtu.be/Ox6DaR7_4ZI).
|
||||
|
||||
* Scan Kubernetes manifest files from a Git repository:
|
||||
|
||||
```sh
|
||||
kubescape scan https://github.com/kubescape/kubescape
|
||||
```
|
||||
|
||||
* Scan with exceptions
|
||||
|
||||
```sh
|
||||
kubescape scan --exceptions examples/exceptions/exclude-kube-namespaces.json
|
||||
```
|
||||
|
||||
Objects with exceptions will be presented as `exclude` and not `fail`.
|
||||
|
||||
[See more examples about exceptions.](/examples/exceptions/README.md)
|
||||
|
||||
* Scan Helm charts
|
||||
|
||||
```sh
|
||||
kubescape scan </path/to/directory>
|
||||
```
|
||||
|
||||
> **Note**
|
||||
> Kubescape will load the default VALUES file.
|
||||
|
||||
* Scan a Kustomize directory
|
||||
|
||||
```sh
|
||||
kubescape scan </path/to/directory>
|
||||
```
|
||||
|
||||
> **Note**
|
||||
> Kubescape will generate Kubernetes YAML objects using a `kustomize` file and scan them for security.
|
||||
|
||||
* Trigger in cluster components for scanning your cluster:
|
||||
|
||||
If kubescape helm chart is install in your cluster we can trigger scanning of the in cluster components from the kubescape CLI.
|
||||
```sh
|
||||
kubescape operator scan config
|
||||
```
|
||||
```sh
|
||||
kubescape operator scan vulnerabilities
|
||||
```
|
||||
|
||||
* Compliance Score
|
||||
|
||||
We offer two important metrics to assess compliance:
|
||||
|
||||
- Control Compliance Score: This score measures the compliance of individual controls within a framework. It is calculated by evaluating the ratio of resources that passed to the total number of resources evaluated against that control.
|
||||
```sh
|
||||
kubescape scan --compliance-threshold <SCORE_VALUE[float32]>
|
||||
```
|
||||
- Framework Compliance Score: This score provides an overall assessment of your cluster's compliance with a specific framework. It is calculated by averaging the Control Compliance Scores of all controls within the framework.
|
||||
```sh
|
||||
kubescape scan framework <FRAMEWORK_NAME> --compliance-threshold <SCORE_VALUE[float32]>
|
||||
```
|
||||
Kubescape scan with compliance score
|
||||
<img src="img/ks-scan-with-compliance.gif">
|
||||
|
||||
### Output formats
|
||||
|
||||
* JSON:
|
||||
#### JSON:
|
||||
|
||||
```sh
|
||||
kubescape scan --format json --format-version v2 --output results.json
|
||||
```
|
||||
```bash
|
||||
kubescape scan --format json --output results.json
|
||||
```
|
||||
|
||||
> **Note**
|
||||
> Add the `--format-version v2` flag for maximum compatibility.
|
||||
#### junit XML:
|
||||
|
||||
* junit XML:
|
||||
```bash
|
||||
kubescape scan --format junit --output results.xml
|
||||
```
|
||||
#### SARIF:
|
||||
|
||||
```sh
|
||||
kubescape scan --format junit --output results.xml
|
||||
```
|
||||
SARIF is a standard format for the output of static analysis tools. It is supported by many tools, including GitHub Code Scanning and Azure DevOps. [Read more about SARIF](https://docs.github.com/en/code-security/secure-coding/sarif-support-for-code-scanning/about-sarif-support-for-code-scanning).
|
||||
|
||||
* PDF:
|
||||
```bash
|
||||
kubescape scan --format sarif --output results.sarif
|
||||
```
|
||||
> **Note**
|
||||
> SARIF format is supported only when scanning local files or git repositories, but not when scanning a running cluster.
|
||||
|
||||
```sh
|
||||
kubescape scan --format pdf --output results.pdf
|
||||
```
|
||||
#### HTML
|
||||
|
||||
_Contributed by [@alegrey91](https://github.com/alegrey91)_
|
||||
|
||||
* Prometheus metrics:
|
||||
|
||||
```
|
||||
kubescape scan --format prometheus
|
||||
```
|
||||
|
||||
_Contributed by [@Joibel](https://github.com/Joibel)_
|
||||
|
||||
* HTML
|
||||
|
||||
```
|
||||
kubescape scan --format html --output results.html
|
||||
```
|
||||
|
||||
* Display all scanned resources (including the resources which passed):
|
||||
|
||||
```sh
|
||||
kubescape scan --verbose
|
||||
```
|
||||
```bash
|
||||
kubescape scan --format html --output results.html
|
||||
```
|
||||
|
||||
## Offline/air-gapped environment support
|
||||
|
||||
@@ -194,7 +274,7 @@ It is possible to run Kubescape offline! Check out our [video tutorial](https:/
|
||||
|
||||
1. Download the controls and save them in the local directory. If no path is specified, they will be saved in `~/.kubescape`.
|
||||
|
||||
```sh
|
||||
```bash
|
||||
kubescape download artifacts --output path/to/local/dir
|
||||
```
|
||||
|
||||
@@ -202,7 +282,7 @@ It is possible to run Kubescape offline! Check out our [video tutorial](https:/
|
||||
|
||||
3. Scan using the downloaded artifacts:
|
||||
|
||||
```sh
|
||||
```bash
|
||||
kubescape scan --use-artifacts-from path/to/local/dir
|
||||
```
|
||||
|
||||
@@ -212,7 +292,7 @@ You can also download a single artifact, and scan with the `--use-from` flag:
|
||||
|
||||
1. Download and save in a file. If no file name is specified, the artifact will be saved as `~/.kubescape/<framework name>.json`.
|
||||
|
||||
```sh
|
||||
```bash
|
||||
kubescape download framework nsa --output /path/nsa.json
|
||||
```
|
||||
|
||||
@@ -220,9 +300,32 @@ You can also download a single artifact, and scan with the `--use-from` flag:
|
||||
|
||||
3. Scan using the downloaded framework:
|
||||
|
||||
```sh
|
||||
```bash
|
||||
kubescape scan framework nsa --use-from /path/nsa.json
|
||||
```
|
||||
## Image scanning
|
||||
|
||||
Kubescape can scan container images for vulnerabilities. It uses [Grype]() to scan the images.
|
||||
|
||||
### Examples
|
||||
|
||||
#### Scan image
|
||||
|
||||
```bash
|
||||
kubescape scan image nginx:1.19.6
|
||||
```
|
||||
|
||||
#### Scan image from a private registry
|
||||
|
||||
```bash
|
||||
kubescape scan image --username myuser --password mypassword myregistry/nginx:1.19.6
|
||||
```
|
||||
|
||||
#### Scan image and see full report
|
||||
|
||||
```bash
|
||||
kubescape scan image nginx:1.19.6 -v
|
||||
```
|
||||
|
||||
## Other ways to use Kubescape
|
||||
|
||||
|
||||
BIN
docs/img/architecture-diagram.png
Normal file
BIN
docs/img/architecture-diagram.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 99 KiB |
101
docs/roadmap.md
101
docs/roadmap.md
@@ -1,100 +1,3 @@
|
||||
# Kubescape project roadmap
|
||||
# Kubescape project roadmap (deprecated 👷)
|
||||
|
||||
## Planning principles
|
||||
|
||||
Kubescape roadmap items are labeled based on where the feature is used and by their maturity.
|
||||
|
||||
The features serve different stages of the workflow of the users:
|
||||
|
||||
* **Development phase** (writing Kubernetes manifests) - example: The VS Code extension is used while editing YAMLs.
|
||||
* **CI phase** (integrating manifests to GIT repo) - example: GitHub action validating HELM charts on PRs.
|
||||
* **CD phase** (deploying applications in Kubernetes) - example: running a cluster scan after a new deployment.
|
||||
* **Monitoring phase** (scanning application in Kubernetes) - example: Prometheus scraping the cluster security risk.
|
||||
|
||||
The items in the Kubescape roadmap are split into 3 major groups based on the feature planning maturity:
|
||||
|
||||
* [Planning](#planning-) - we have tickets open for these issues with a more or less clear vision of design.
|
||||
* [Backlog](#backlog-) - features that were discussed at a high level but are not ready for development.
|
||||
* [Wishlist](#wishlist-) - features that we are dreaming of in 😀 and want to push them gradually forward.
|
||||
|
||||
|
||||
## Planning 👷
|
||||
|
||||
* ### eBPF based anomaly detection in workloads
|
||||
|
||||
The introduction of runtime anomaly detection using eBPF (extended Berkeley Packet Filter) events marks an addition to the Kubescape project's development roadmap. This feature aims to leverage the high-performance monitoring capabilities of eBPF to detect abnormal behavior within Kubernetes workloads in real-time. By capturing and analyzing eBPF events, Kubescape will be able to identify deviations from application profiles, such as unexpected network connections, unauthorized process executions, or unusual system calls, which could indicate a security breach. This anomaly detection mechanism is designed to operate with minimal overhead, ensuring that security monitoring does not compromise system performance.
|
||||
|
||||
* ### Enriching Vulnerability scan results with advanced prioritization data sources
|
||||
|
||||
Integrating EPSS (Exploit Prediction Scoring System) and CISA-KEV (Known Exploited Vulnerabilities) metrics into Kubescape's CLI and Operator vulnerability scan results represents a significant enhancement in the project's roadmap. This integration aims to enrich the vulnerability management process by providing more contextual and predictive insights into the security risks associated with Kubernetes clusters. By leveraging EPSS scores, Kubescape will offer predictions on the likelihood of a vulnerability being exploited, enabling users to prioritize remediations based on risk rather than just vulnerability presence. The addition of CISA-KEV metrics further enhances this capability by flagging vulnerabilities that are actively being exploited in the wild, as identified by the Cybersecurity and Infrastructure Security Agency (CISA). This dual approach ensures that Kubescape users are not only informed about the vulnerabilities in their environments but are also equipped with critical information on which vulnerabilities to remediate first, based on their exploitability and active exploitation trends. This strategic enhancement to Kubescape's vulnerability scan results will provide users with a powerful tool for making informed, risk-based security decisions in their Kubernetes environments.
|
||||
|
||||
* ### Integration with image registries
|
||||
|
||||
We want to expand Kubescape to integrate with different image registries and read image vulnerability information from there. This will allow Kubescape to give contextual security information about vulnerabilities. Container registry integration.
|
||||
|
||||
* ### Kubescape CLI control over cluster operations
|
||||
|
||||
Add functionality to Kubescape CLI to trigger operations in Kubescape cluster components (example: trigger image scans, etc.)
|
||||
|
||||
* ### Git integration for pull requests
|
||||
|
||||
Create insightful GitHub actions for Kubescape.
|
||||
|
||||
## Backlog 📅
|
||||
|
||||
* ### JSON path for HELM charts
|
||||
|
||||
Today, Kubescape can point to issues in the Kubernetes object. We want to develop this feature so Kubescape will be able to point to the misconfigured source file (HELM).
|
||||
|
||||
* ### Create Kubescape HELM plugin
|
||||
|
||||
Producing scan results in the context of HELM.
|
||||
|
||||
* ### Kubescape based admission controller
|
||||
|
||||
Implement admission controller API for Kubescape microservice to enable users to use Kubescape rules as policies.
|
||||
|
||||
## Wishlist 💭
|
||||
|
||||
* ### Integrate with other Kubernetes CLI tools
|
||||
|
||||
Use Kubescape as a YAML validator for `kubectl` and others.
|
||||
|
||||
* ### Kubernetes audit log integration
|
||||
|
||||
Connect Kubescape to the audit log stream to enable it to produce more contextual security information based on how the API service is used.
|
||||
|
||||
* ### TUI for Kubescape
|
||||
|
||||
Interactive terminal based user interface which helps to analyze and fix issues.
|
||||
|
||||
* ### Scanning images with GO for vulnerabilities
|
||||
|
||||
Images scanners cannot determine which packages were used to build Go executables and we want to scan them for vulnerabilities.
|
||||
|
||||
* ### Scanning Dockerfile-s for security best practices
|
||||
|
||||
Scan image or Dockerfile to determine whether it is using security best practices (like root containers).
|
||||
|
||||
* ### Custom controls and rules
|
||||
|
||||
Enable users to define their own Rego base rules.
|
||||
|
||||
* ### More CI/CD tool integration
|
||||
|
||||
Jenkins and etc. 😀
|
||||
|
||||
|
||||
## Completed features 🎓
|
||||
|
||||
* Kubelet configuration validation
|
||||
* API server configuration validation
|
||||
* Image vulnerability scanning based controls
|
||||
* Assisted remediation (telling where/what to fix)
|
||||
* Integration with Prometheus
|
||||
* Configuration of controls (customizing rules for a given environment)
|
||||
* Installation in the cluster for continuous monitoring
|
||||
* Host scanner
|
||||
* Cloud vendor API integration
|
||||
* Custom exceptions
|
||||
* Custom frameworks
|
||||
This roadmap page has been replaced in favor of [centralized project roadmap page](https://github.com/kubescape/project-governance/blob/main/ROADMAP.md)
|
||||
|
||||
23
downloader/main.go
Normal file
23
downloader/main.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/kubescape/go-logger"
|
||||
"github.com/kubescape/go-logger/helpers"
|
||||
"github.com/kubescape/kubescape/v3/core/core"
|
||||
metav1 "github.com/kubescape/kubescape/v3/core/meta/datastructures/v1"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ks := core.NewKubescape()
|
||||
downloads := []metav1.DownloadInfo{
|
||||
{Target: "artifacts"}, // download all artifacts
|
||||
{Target: "framework", Identifier: "security"}, // force add the "security" framework
|
||||
}
|
||||
for _, download := range downloads {
|
||||
if err := ks.Download(context.Background(), &download); err != nil {
|
||||
logger.L().Error("failed to download artifact", helpers.Error(err), helpers.String("target", download.Target))
|
||||
}
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user