Compare commits

...

3 Commits

Author SHA1 Message Date
Daniel Grunberger
8b32de42a2 validate sarif output
Signed-off-by: Daniel Grunberger <danielgrunberger@armosec.io>
2023-09-03 16:45:58 +03:00
Daniel Grunberger
b7a9a1f3d7 rm from httphandler
Signed-off-by: Daniel Grunberger <danielgrunberger@armosec.io>
2023-09-03 09:37:12 +03:00
Daniel Grunberger
a0b6f5ffac move context flag to root
Signed-off-by: Daniel Grunberger <danielgrunberger@armosec.io>
2023-08-31 16:35:09 +03:00
9 changed files with 123 additions and 81 deletions

View File

@@ -6,6 +6,7 @@ import (
logger "github.com/kubescape/go-logger"
"github.com/kubescape/go-logger/helpers"
"github.com/kubescape/k8s-interface/k8sinterface"
"github.com/kubescape/kubescape/v2/cmd/completion"
"github.com/kubescape/kubescape/v2/cmd/config"
"github.com/kubescape/kubescape/v2/cmd/download"
@@ -49,6 +50,13 @@ func getRootCmd(ks meta.IKubescape) *cobra.Command {
Use: "kubescape",
Short: "Kubescape is a tool for testing Kubernetes security posture. Docs: https://hub.armosec.io/docs",
Example: ksExamples,
PersistentPreRun: func(cmd *cobra.Command, args []string) {
k8sinterface.SetClusterContextName(rootInfo.KubeContext)
initLogger()
initLoggerLevel()
initEnvironment()
initCacheDir()
},
}
if cautils.IsKrewPlugin() {
@@ -76,8 +84,7 @@ func getRootCmd(ks meta.IKubescape) *cobra.Command {
rootCmd.PersistentFlags().BoolVarP(&rootInfo.DisableColor, "disable-color", "", false, "Disable color output for logging")
rootCmd.PersistentFlags().BoolVarP(&rootInfo.EnableColor, "enable-color", "", false, "Force enable color output for logging")
cobra.OnInitialize(initLogger, initLoggerLevel, initEnvironment, initCacheDir)
rootCmd.PersistentFlags().StringVarP(&rootInfo.KubeContext, "kube-context", "", "", "Kube context. Default will use the current-context")
// Supported commands
rootCmd.AddCommand(scan.GetScanCommand(ks))
rootCmd.AddCommand(download.GetDownloadCmd(ks))

View File

@@ -6,7 +6,6 @@ import (
"fmt"
"strings"
"github.com/kubescape/k8s-interface/k8sinterface"
"github.com/kubescape/kubescape/v2/core/cautils"
"github.com/kubescape/kubescape/v2/core/cautils/getter"
"github.com/kubescape/kubescape/v2/core/meta"
@@ -63,17 +62,12 @@ func GetScanCommand(ks meta.IKubescape) *cobra.Command {
}
return nil
},
PreRun: func(cmd *cobra.Command, args []string) {
k8sinterface.SetClusterContextName(scanInfo.KubeContext)
},
PostRun: func(cmd *cobra.Command, args []string) {
// TODO - revert context
},
}
scanCmd.PersistentFlags().StringVarP(&scanInfo.AccountID, "account", "", "", "Kubescape SaaS account ID. Default will load account ID from cache")
scanCmd.PersistentFlags().StringVarP(&scanInfo.KubeContext, "kube-context", "", "", "Kube context. Default will use the current-context")
scanCmd.PersistentFlags().StringVar(&scanInfo.ControlsInputs, "controls-config", "", "Path to an controls-config obj. If not set will download controls-config from ARMO management portal")
scanCmd.PersistentFlags().StringVar(&scanInfo.UseExceptions, "exceptions", "", "Path to an exceptions obj. If not set will download exceptions from ARMO management portal")
scanCmd.PersistentFlags().StringVar(&scanInfo.UseArtifactsFrom, "use-artifacts-from", "", "Load artifacts from local directory. If not used will download them")

View File

@@ -13,6 +13,7 @@ type RootInfo struct {
DisableColor bool // Disable Color
EnableColor bool // Force enable Color
DiscoveryServerURL string // Discovery Server URL (See https://github.com/kubescape/backend/tree/main/pkg/servicediscovery)
KubeContext string // context name
}
type CloudURLs struct {
CloudReportURL string

View File

@@ -129,7 +129,6 @@ type ScanInfo struct {
HostSensorYamlPath string // Path to hostsensor file
Local bool // Do not submit results
AccountID string // account ID
KubeContext string // context name
FrameworkScan bool // false if scanning control
ScanAll bool // true if scan all frameworks
OmitRawResources bool // true if omit raw resources from the output

View File

@@ -106,9 +106,8 @@ func GetOutputPrinters(scanInfo *cautils.ScanInfo, ctx context.Context, clusterN
outputPrinters := make([]printer.IPrinter, 0)
for _, format := range formats {
if !resultshandling.ValidatePrinter(scanInfo.ScanType, format) {
logger.L().Ctx(ctx).Fatal(fmt.Sprintf("Unsupported output format: %s", format))
continue
if err := resultshandling.ValidatePrinter(scanInfo.ScanType, scanInfo.GetScanningContext(), format); err != nil {
logger.L().Ctx(ctx).Fatal(err.Error())
}
printerHandler := resultshandling.NewPrinter(ctx, format, scanInfo.FormatVersion, scanInfo.PrintAttackTree, scanInfo.VerboseMode, cautils.ViewTypes(scanInfo.View), clusterName)

View File

@@ -176,6 +176,7 @@ func (sp *SARIFPrinter) printConfigurationScan(ctx context.Context, opaSessionOb
locationResolver, err := locationresolver.NewFixPathLocationResolver(rsrcAbsPath)
if err != nil {
logger.L().Debug("failed to create location resolver", helpers.Error(err))
continue
}
for _, toPin := range result.AssociatedControls {

View File

@@ -132,16 +132,26 @@ func NewPrinter(ctx context.Context, printFormat, formatVersion string, verboseM
}
}
func ValidatePrinter(scanType cautils.ScanTypes, printFormat string) bool {
if scanType != cautils.ScanTypeImage {
return true
func ValidatePrinter(scanType cautils.ScanTypes, scanContext cautils.ScanningContext, printFormat string) error {
if scanType == cautils.ScanTypeImage {
// supported types for image scanning
switch printFormat {
case printer.JsonFormat, printer.PrettyFormat, printer.SARIFFormat:
return nil
default:
return fmt.Errorf("format \"%s\"is not supported for image scanning", printFormat)
}
}
// supported types for image scanning
switch printFormat {
case printer.JsonFormat, printer.PrettyFormat, printer.SARIFFormat:
return true
default:
return false
if printFormat == printer.SARIFFormat {
// supported types for SARIF
switch scanContext {
case cautils.ContextDir, cautils.ContextFile, cautils.ContextGitLocal:
return nil
default:
return fmt.Errorf("format \"%s\" is only supported when scanning local files", printFormat)
}
}
return nil
}

View File

@@ -2,12 +2,14 @@ package resultshandling
import (
"context"
"errors"
"testing"
"github.com/kubescape/kubescape/v2/core/cautils"
"github.com/kubescape/kubescape/v2/core/pkg/resultshandling/printer"
"github.com/kubescape/opa-utils/reporthandling/results/v1/reportsummary"
reporthandlingv2 "github.com/kubescape/opa-utils/reporthandling/v2"
"github.com/stretchr/testify/assert"
)
type DummyReporter struct{}
@@ -59,92 +61,123 @@ func TestResultsHandlerHandleResultsPrintsResultsToUI(t *testing.T) {
func TestValidatePrinter(t *testing.T) {
tests := []struct {
name string
scanType cautils.ScanTypes
format string
expected bool
name string
scanType cautils.ScanTypes
scanContext cautils.ScanningContext
format string
expectErr error
}{
{
name: "json format for cluster scan",
scanType: cautils.ScanTypeCluster,
format: printer.JsonFormat,
expected: true,
name: "json format for cluster scan should not return error",
scanType: cautils.ScanTypeCluster,
format: printer.JsonFormat,
expectErr: nil,
},
{
name: "junit format for cluster scan",
scanType: cautils.ScanTypeCluster,
format: printer.JunitResultFormat,
expected: true,
name: "junit format for cluster scan should return error",
scanType: cautils.ScanTypeCluster,
format: printer.JunitResultFormat,
expectErr: nil,
},
{
name: "sarif format for cluster scan",
scanType: cautils.ScanTypeCluster,
format: printer.SARIFFormat,
expected: true,
name: "sarif format for cluster scan and git url context should not return error",
scanType: cautils.ScanTypeCluster,
scanContext: cautils.ContextGitLocal,
format: printer.SARIFFormat,
expectErr: nil,
},
{
name: "pretty format for cluster scan",
scanType: cautils.ScanTypeCluster,
format: printer.PrettyFormat,
expected: true,
name: "pretty format for cluster scan should not return error",
scanType: cautils.ScanTypeCluster,
format: printer.PrettyFormat,
expectErr: nil,
},
{
name: "html format for cluster scan",
scanType: cautils.ScanTypeCluster,
format: printer.HtmlFormat,
expected: true,
name: "html format for cluster scan should not return error",
scanType: cautils.ScanTypeCluster,
format: printer.HtmlFormat,
expectErr: nil,
},
{
name: "prometheus format for cluster scan",
scanType: cautils.ScanTypeCluster,
format: printer.PrometheusFormat,
expected: true,
name: "prometheus format for cluster scan should not return error",
scanType: cautils.ScanTypeCluster,
format: printer.PrometheusFormat,
expectErr: nil,
},
{
name: "json format for image scan",
scanType: cautils.ScanTypeImage,
format: printer.JsonFormat,
expected: true,
name: "json format for image scan should not return error",
scanType: cautils.ScanTypeImage,
format: printer.JsonFormat,
expectErr: nil,
},
{
name: "junit format for image scan",
scanType: cautils.ScanTypeImage,
format: printer.JunitResultFormat,
expected: false,
name: "junit format for image scan should return error",
scanType: cautils.ScanTypeImage,
format: printer.JunitResultFormat,
expectErr: errors.New("format \"junit\"is not supported for image scanning"),
},
{
name: "sarif format for image scan",
scanType: cautils.ScanTypeImage,
format: printer.SARIFFormat,
expected: true,
name: "sarif format for image scan should not return error",
scanType: cautils.ScanTypeImage,
format: printer.SARIFFormat,
expectErr: nil,
},
{
name: "pretty format for image scan",
scanType: cautils.ScanTypeImage,
format: printer.PrettyFormat,
expected: true,
name: "pretty format for image scan should not return error",
scanType: cautils.ScanTypeImage,
format: printer.PrettyFormat,
expectErr: nil,
},
{
name: "html format for image scan",
scanType: cautils.ScanTypeImage,
format: printer.HtmlFormat,
expected: false,
name: "html format for image scan should return error",
scanType: cautils.ScanTypeImage,
format: printer.HtmlFormat,
expectErr: errors.New("format \"html\"is not supported for image scanning"),
},
{
name: "prometheus format for image scan",
scanType: cautils.ScanTypeImage,
format: printer.PrometheusFormat,
expected: false,
name: "prometheus format for image scan should return error",
scanType: cautils.ScanTypeImage,
format: printer.PrometheusFormat,
expectErr: errors.New("format \"prometheus\"is not supported for image scanning"),
},
{
name: "sarif format for cluster context should return error",
scanContext: cautils.ContextCluster,
format: printer.SARIFFormat,
expectErr: errors.New("format \"sarif\" is only supported when scanning local files"),
},
{
name: "sarif format for remote url context should return error",
scanContext: cautils.ContextGitURL,
format: printer.SARIFFormat,
expectErr: errors.New("format \"sarif\" is only supported when scanning local files"),
},
{
name: "sarif format for local dir context should not return error",
scanContext: cautils.ContextDir,
format: printer.SARIFFormat,
expectErr: nil,
},
{
name: "sarif format for local file context should not return error",
scanContext: cautils.ContextFile,
format: printer.SARIFFormat,
expectErr: nil,
},
{
name: "sarif format for local git context should not return error",
scanContext: cautils.ContextGitLocal,
format: printer.SARIFFormat,
expectErr: nil,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := ValidatePrinter(tt.scanType, tt.format)
if got != tt.expected {
t.Errorf("%s failed - got = %v, want %v", tt.name, got, tt.expected)
}
got := ValidatePrinter(tt.scanType, tt.scanContext, tt.format)
assert.Equal(t, tt.expectErr, got)
})
}

View File

@@ -70,7 +70,6 @@ func scan(ctx context.Context, scanInfo *cautils.ScanInfo, scanID string) (*repo
trace.WithAttributes(attribute.String("excludedNamespaces", scanInfo.ExcludedNamespaces)),
trace.WithAttributes(attribute.String("includeNamespaces", scanInfo.IncludeNamespaces)),
trace.WithAttributes(attribute.String("hostSensorYamlPath", scanInfo.HostSensorYamlPath)),
trace.WithAttributes(attribute.String("kubeContext", scanInfo.KubeContext)),
)
result, err := ks.Scan(ctx, scanInfo)
@@ -151,8 +150,8 @@ func getScanCommand(scanRequest *utilsmetav1.PostScanRequest, scanID string) *ca
scanInfo.Output = filepath.Join(OutputDir, scanID)
// *** end ***
// Set default KubeContext from scanInfo input
k8sinterface.SetClusterContextName(scanInfo.KubeContext)
// Set default KubeContext from current context
k8sinterface.SetClusterContextName(k8sinterface.GetContextName())
return scanInfo
}
@@ -173,7 +172,6 @@ func defaultScanInfo() *cautils.ScanInfo {
if !envToBool("KS_DOWNLOAD_ARTIFACTS", false) {
scanInfo.UseArtifactsFrom = getter.DefaultLocalStore // Load files from cache (this will prevent kubescape fom downloading the artifacts every time)
}
scanInfo.KubeContext = envToString("KS_CONTEXT", "") // publish results to Kubescape SaaS
return scanInfo
}