mirror of
https://github.com/kubescape/kubescape.git
synced 2026-04-06 18:56:53 +00:00
* Fix issue for scanning list obj * Fix go mod in httphandler pkg * Broken links fix in roadmap.md Planning, backlog, and wishlist links were not taking to the required section. * override infoMap only if it's not nil * improved icon of kubescape in readme * Support scanning several files * gramatical improvements * docs(readme): Star → star * Fix issues according to review * Handle with issues caused by updating opa-utils * Fix scanning ListObj following reviews * Update core/pkg/resourcehandler/filesloader.go Co-authored-by: Vlad Klokun <vladklokun@users.noreply.github.com> * Update completion.go * Added fixed control input * update go.mod * Print chart name log when fail to generate * Change formatting to %s * Added resource prioritization information, raw resource will be sent on the result object * Merging typo fixes from master (#772) * greetings * Update aws.sh simplified the comment * typo: In the title and h1 element Their was a typo in index.html file. * punctuation changes * docs : added gitpod badge in readme.md * fixed typos * some grammar mistake is corrected inPULL_REQUEST_TEMPLATE.md file * Updated README.md file Added link to CONTRIBUTING.md file in a line in README. * Added link to code of conduct file I have added link to the code of conduct file and fixed some problems in the Readme file. * Fixed readme * Added alpine tag Adding alpine tag instead of latest and removing repeating commands * roadmap.md file is modified * Automatically Close "Typo" labelled Issue * build.py is modified * modified PR template * Fixed some typos in feature_request.md "." at the end of the headings were missing and all the text were in same line. Now this gives a clear and concise view of the texts. * fixed the typo in docs/index.html Found and fixed typo in the 'alt' attribute of img tag * Update PULL_REQUEST_TEMPLATE.md Co-authored-by: Krishna Agarwal <dmkrishna.agarwal@gmail.com> Co-authored-by: Saswata Senapati <74651639+saswat16@users.noreply.github.com> Co-authored-by: Rahul Singh <110548934+rahuldhirendersingh@users.noreply.github.com> Co-authored-by: deepuyadav004 <deepuyadavze@gmail.com> Co-authored-by: kartik <97971066+kartikgajjar7@users.noreply.github.com> Co-authored-by: Rounak-28 <95576871+Rounak-28@users.noreply.github.com> Co-authored-by: pwnb0y <vickykr07@yahoo.com> Co-authored-by: Ben Hirschberg <59160382+slashben@users.noreply.github.com> Co-authored-by: Saptarshi Sarkar <saptarshi.programmer@gmail.com> Co-authored-by: Rahul Surwade <93492791+RahulSurwade08@users.noreply.github.com> Co-authored-by: Suhas Gumma <43647369+suhasgumma@users.noreply.github.com> Co-authored-by: Kamal Nayan <95926324+legendarykamal@users.noreply.github.com> Co-authored-by: TarangVerma <90996971+TarangVerma@users.noreply.github.com> Co-authored-by: avikittu <65793296+avikittu@users.noreply.github.com> * update logger version * update logger version (#773) * Fixed: Kubescape fails to authenticate remote private Github repo (#721) * grammar error fixer in CONTRIBUTING.md * scanning private git repository is available * giturl to gitapi * NO TOKEN error functionality added * Used GetToken method of giturl.IGitAPPI for auth Co-authored-by: satyam kale <satyamkale271@gmail.com> Co-authored-by: Ben Hirschberg <59160382+slashben@users.noreply.github.com> * bump opa-utils to 181 * Option to force enable color output (closes #560) (#767) * Option to force enable color output (closes #560) (cherry picked from commit 4f951781ee8dd6bb451ac7d159787f47e4b07379) * Update go.mod * update scanner image * Update host scanner image (#774) * update logger version * update scanner image * remove windows exe extension * Remove windows extension build (#775) * update logger version * update scanner image * remove windows exe extension * commened out prioritization logic * Edit Junit output (#802) * Edit Junit output * Update go sum * Following review * update AdoptClusterName * Print line separator only if some controls failed (#813) * removed the extra 'download' word from the example (#810) it was confusing to understand the download command because there was an extra 'download' mentioned * Prioritization (#815) * removed commented out code * Added attack tracks information to prioritization algorithm * bump opa-utils * go mod tidy * go mod tidy * CR changes * Issue 613 cluster name (#783) * added --clusterName flag (#613) Signed-off-by: Anubhav Gupta <mail.anubhav06@gmail.com> * update flag name to --cluster-name Signed-off-by: Anubhav Gupta <mail.anubhav06@gmail.com> Signed-off-by: Anubhav Gupta <mail.anubhav06@gmail.com> * Per 307 fail on severity counters (#831) * feat: fail on exceeding severity thresholds (#830) - Add support for severity counters - Add support for CLI flags that set severity thresholds - Terminate Kubescape with an exit code 1 if scan results exceed the severity thresholds * Update opa-utils pkg version Co-authored-by: Vlad Klokun <vladklokun@users.noreply.github.com> * Fix merge conflict * typo in .gitignore file (#833) * remove unsupported installation method * fixed welcome message * fixed merge * fixed attack tracks loading logic * add flag validation for --account-id (#605) (#793) * add flag validation for --account-id (#605) Signed-off-by: Anubhav Gupta <mail.anubhav06@gmail.com> * add flag validation for --client-id & --secret-key Signed-off-by: Anubhav Gupta <mail.anubhav06@gmail.com> * Validation method should be a member function * Adding unit tests for credentials validate Signed-off-by: Anubhav Gupta <mail.anubhav06@gmail.com> Co-authored-by: David Wertenteil <dwertent@armosec.io> * Scan Kustomize Directory (#795) * Scan Kustomize Files * update 'scam Kustomize Directory' documentation in Readme.md * go get * go get inside httphandler * SourceTypeKustomizeDirectory * Added Scan for Kustomization File Co-authored-by: David Wertenteil <dwertent@armosec.io> * feat: unify severity threshold into one CLI flag (#838) * feat: unify severity threshold into one CLI flag Before this commit, severity threshold flags were separated by severity. This commit unifies these thresholds into one flag that forces Kubescape to terminate with an exit code 1 if there was at least one failed control at the specified severity threshold or above. * chore: update opa utils version * chore: update opa-utils in httphandler * feat: dont enforce severity by default Previous iteration of supporting the severity threshold enforced it even if the severity threshold was not explicitly specified. This change enforces the severity threshold only if it has been explicitly set. * refactor: clarify flagValidationFramework func name This change clarifies the meaning of the function that validates the scan info for the `scan framework` command. It achieves this by renaming the `flagValidationFramework` function to `validateFrameworkScanInfo`. * Merge branch 'master' into dev Signed-off-by: Anubhav Gupta <mail.anubhav06@gmail.com> Co-authored-by: Moshe-Rappaport-CA <moshep@armosec.io> Co-authored-by: Moshe Rappaport <89577611+Moshe-Rappaport-CA@users.noreply.github.com> Co-authored-by: Om Raut <33827410+om2137@users.noreply.github.com> Co-authored-by: Kamal Nayan <95926324+legendarykamal@users.noreply.github.com> Co-authored-by: Vlad Klokun <vladklokun@users.noreply.github.com> Co-authored-by: Chirag Arora <84070677+Chirag8023@users.noreply.github.com> Co-authored-by: shm12 <shmuelb@armosec.io> Co-authored-by: Amir Malka <amirm@armosec.io> Co-authored-by: Krishna Agarwal <dmkrishna.agarwal@gmail.com> Co-authored-by: Saswata Senapati <74651639+saswat16@users.noreply.github.com> Co-authored-by: Rahul Singh <110548934+rahuldhirendersingh@users.noreply.github.com> Co-authored-by: deepuyadav004 <deepuyadavze@gmail.com> Co-authored-by: kartik <97971066+kartikgajjar7@users.noreply.github.com> Co-authored-by: Rounak-28 <95576871+Rounak-28@users.noreply.github.com> Co-authored-by: pwnb0y <vickykr07@yahoo.com> Co-authored-by: Ben Hirschberg <59160382+slashben@users.noreply.github.com> Co-authored-by: Saptarshi Sarkar <saptarshi.programmer@gmail.com> Co-authored-by: Rahul Surwade <93492791+RahulSurwade08@users.noreply.github.com> Co-authored-by: Suhas Gumma <43647369+suhasgumma@users.noreply.github.com> Co-authored-by: TarangVerma <90996971+TarangVerma@users.noreply.github.com> Co-authored-by: avikittu <65793296+avikittu@users.noreply.github.com> Co-authored-by: satyam kale <satyamkale271@gmail.com> Co-authored-by: Aditya Pratap Singh <adityapratapsingh51@gmail.com> Co-authored-by: Ashray Shetty <ashrayshetty1999@gmail.com> Co-authored-by: Anubhav Gupta <mail.anubhav06@gmail.com> Co-authored-by: Meyazhagan <meyazhagan.ofcl@gmail.com>
213 lines
6.9 KiB
Go
213 lines
6.9 KiB
Go
package scan
|
||
|
||
import (
|
||
"errors"
|
||
"fmt"
|
||
"io"
|
||
"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"
|
||
|
||
logger "github.com/kubescape/go-logger"
|
||
"github.com/kubescape/go-logger/helpers"
|
||
"github.com/kubescape/kubescape/v2/core/cautils"
|
||
"github.com/kubescape/kubescape/v2/core/meta"
|
||
|
||
"github.com/enescakir/emoji"
|
||
"github.com/spf13/cobra"
|
||
)
|
||
|
||
var (
|
||
frameworkExample = `
|
||
# Scan all frameworks and submit the results
|
||
kubescape scan framework all --submit
|
||
|
||
# Scan the NSA framework
|
||
kubescape scan framework nsa
|
||
|
||
# Scan the NSA and MITRE framework
|
||
kubescape scan framework nsa,mitre
|
||
|
||
# Scan all frameworks
|
||
kubescape scan framework all
|
||
|
||
# Scan kubernetes YAML manifest files (single file or glob)
|
||
kubescape scan framework nsa *.yaml
|
||
|
||
Run 'kubescape list frameworks' for the list of supported frameworks
|
||
`
|
||
|
||
ErrUnknownSeverity = errors.New("unknown severity")
|
||
)
|
||
|
||
func getFrameworkCmd(ks meta.IKubescape, scanInfo *cautils.ScanInfo) *cobra.Command {
|
||
|
||
return &cobra.Command{
|
||
Use: "framework <framework names list> [`<glob pattern>`/`-`] [flags]",
|
||
Short: "The framework you wish to use. Run 'kubescape list frameworks' for the list of supported frameworks",
|
||
Example: frameworkExample,
|
||
Long: "Execute a scan on a running Kubernetes cluster or `yaml`/`json` files (use glob) or `-` for stdin",
|
||
Args: func(cmd *cobra.Command, args []string) error {
|
||
if len(args) > 0 {
|
||
frameworks := strings.Split(args[0], ",")
|
||
if len(frameworks) > 1 {
|
||
for _, framework := range frameworks {
|
||
if framework == "" {
|
||
return fmt.Errorf("usage: <framework-0>,<framework-1>")
|
||
}
|
||
}
|
||
}
|
||
} else {
|
||
return fmt.Errorf("requires at least one framework name")
|
||
}
|
||
return nil
|
||
},
|
||
RunE: func(cmd *cobra.Command, args []string) error {
|
||
|
||
if err := validateFrameworkScanInfo(scanInfo); err != nil {
|
||
return err
|
||
}
|
||
scanInfo.FrameworkScan = true
|
||
|
||
var frameworks []string
|
||
|
||
if len(args) == 0 { // scan all frameworks
|
||
scanInfo.ScanAll = true
|
||
} else {
|
||
// Read frameworks from input args
|
||
frameworks = strings.Split(args[0], ",")
|
||
if cautils.StringInSlice(frameworks, "all") != cautils.ValueNotFound {
|
||
scanInfo.ScanAll = true
|
||
frameworks = []string{}
|
||
}
|
||
if len(args) > 1 {
|
||
if len(args[1:]) == 0 || args[1] != "-" {
|
||
scanInfo.InputPatterns = args[1:]
|
||
} else { // store stdin to file - do NOT move to separate function !!
|
||
tempFile, err := os.CreateTemp(".", "tmp-kubescape*.yaml")
|
||
if err != nil {
|
||
return err
|
||
}
|
||
defer os.Remove(tempFile.Name())
|
||
|
||
if _, err := io.Copy(tempFile, os.Stdin); err != nil {
|
||
return err
|
||
}
|
||
scanInfo.InputPatterns = []string{tempFile.Name()}
|
||
}
|
||
}
|
||
}
|
||
scanInfo.FrameworkScan = true
|
||
|
||
scanInfo.SetPolicyIdentifiers(frameworks, apisv1.KindFramework)
|
||
|
||
results, err := ks.Scan(scanInfo)
|
||
if err != nil {
|
||
logger.L().Fatal(err.Error())
|
||
}
|
||
|
||
if err = results.HandleResults(); err != nil {
|
||
logger.L().Fatal(err.Error())
|
||
}
|
||
if !scanInfo.VerboseMode {
|
||
cautils.SimpleDisplay(os.Stderr, "%s Run with '--verbose'/'-v' flag for detailed resources view\n\n", emoji.Detective)
|
||
}
|
||
if results.GetRiskScore() > float32(scanInfo.FailThreshold) {
|
||
logger.L().Fatal("scan risk-score is above permitted threshold", helpers.String("risk-score", fmt.Sprintf("%.2f", results.GetRiskScore())), helpers.String("fail-threshold", fmt.Sprintf("%.2f", scanInfo.FailThreshold)))
|
||
}
|
||
|
||
enforceSeverityThresholds(&results.GetData().Report.SummaryDetails.SeverityCounters, scanInfo, terminateOnExceedingSeverity)
|
||
return nil
|
||
},
|
||
}
|
||
}
|
||
|
||
// countersExceedSeverityThreshold returns true if severity of failed controls exceed the set severity threshold, else returns false
|
||
func countersExceedSeverityThreshold(severityCounters reportsummary.ISeverityCounters, scanInfo *cautils.ScanInfo) (bool, error) {
|
||
targetSeverity := scanInfo.FailThresholdSeverity
|
||
if err := validateSeverity(targetSeverity); err != nil {
|
||
return false, err
|
||
}
|
||
|
||
getFailedResourcesFuncsBySeverity := []struct {
|
||
SeverityName string
|
||
GetFailedResources func() int
|
||
}{
|
||
{reporthandlingapis.SeverityLowString, severityCounters.NumberOfResourcesWithLowSeverity},
|
||
{reporthandlingapis.SeverityMediumString, severityCounters.NumberOfResourcesWithMediumSeverity},
|
||
{reporthandlingapis.SeverityHighString, severityCounters.NumberOfResourcesWithHighSeverity},
|
||
{reporthandlingapis.SeverityCriticalString, severityCounters.NumberOfResourcesWithCriticalSeverity},
|
||
}
|
||
|
||
targetSeverityIdx := 0
|
||
for idx, description := range getFailedResourcesFuncsBySeverity {
|
||
if strings.EqualFold(description.SeverityName, targetSeverity) {
|
||
targetSeverityIdx = idx
|
||
break
|
||
}
|
||
}
|
||
|
||
for _, description := range getFailedResourcesFuncsBySeverity[targetSeverityIdx:] {
|
||
failedResourcesCount := description.GetFailedResources()
|
||
if failedResourcesCount > 0 {
|
||
return true, nil
|
||
}
|
||
}
|
||
|
||
return false, nil
|
||
|
||
}
|
||
|
||
// terminateOnExceedingSeverity terminates the application on exceeding severity
|
||
func terminateOnExceedingSeverity(scanInfo *cautils.ScanInfo, l logger.ILogger) {
|
||
l.Fatal("result exceeds severity threshold", helpers.String("set severity threshold", scanInfo.FailThresholdSeverity))
|
||
}
|
||
|
||
// enforceSeverityThresholds ensures that the scan results are below the defined severity threshold
|
||
//
|
||
// The function forces the application to terminate with an exit code 1 if at least one control failed control that exceeds the set severity threshold
|
||
func enforceSeverityThresholds(severityCounters reportsummary.ISeverityCounters, scanInfo *cautils.ScanInfo, onExceed func(*cautils.ScanInfo, logger.ILogger)) {
|
||
// If a severity threshold is not set, we don’t need to enforce it
|
||
if scanInfo.FailThresholdSeverity == "" {
|
||
return
|
||
}
|
||
|
||
if val, err := countersExceedSeverityThreshold(severityCounters, scanInfo); val && err == nil {
|
||
onExceed(scanInfo, logger.L())
|
||
} else if err != nil {
|
||
logger.L().Fatal(err.Error())
|
||
}
|
||
}
|
||
|
||
// validateSeverity returns an error if a given severity is not known, nil otherwise
|
||
func validateSeverity(severity string) error {
|
||
for _, val := range reporthandlingapis.GetSupportedSeverities() {
|
||
if strings.EqualFold(severity, val) {
|
||
return nil
|
||
}
|
||
}
|
||
return ErrUnknownSeverity
|
||
|
||
}
|
||
|
||
// validateFrameworkScanInfo validates the scan info struct for the `scan framework` command
|
||
func validateFrameworkScanInfo(scanInfo *cautils.ScanInfo) error {
|
||
if scanInfo.Submit && scanInfo.Local {
|
||
return fmt.Errorf("you can use `keep-local` or `submit`, but not both")
|
||
}
|
||
if 100 < scanInfo.FailThreshold || 0 > scanInfo.FailThreshold {
|
||
return fmt.Errorf("bad argument: out of range threshold")
|
||
}
|
||
|
||
severity := scanInfo.FailThresholdSeverity
|
||
if err := validateSeverity(severity); severity != "" && err != nil {
|
||
return err
|
||
}
|
||
|
||
// Validate the user's credentials
|
||
return scanInfo.Credentials.Validate()
|
||
}
|