diff --git a/README.md b/README.md index 64dd1421..eaa06138 100644 --- a/README.md +++ b/README.md @@ -58,6 +58,7 @@ Want to contribute? Want to discuss something? Have an issue? * [Overview](https://youtu.be/wdBkt_0Qhbg) * [Scanning Kubernetes YAML files](https://youtu.be/Ox6DaR7_4ZI) +* [Scan Kubescape on an air-gapped environment (offline support)](https://youtu.be/IGXL9s37smM) * [Managing exceptions in the Kubescape SaaS version](https://youtu.be/OzpvxGmCR80) ## Install on Windows @@ -158,8 +159,9 @@ kubescape scan framework nsa --format prometheus ``` #### Scan with exceptions, objects with exceptions will be presented as `exclude` and not `fail` +[Full documentation](examples/exceptions/README.md) ``` -kubescape scan framework nsa --exceptions examples/exceptions.json +kubescape scan framework nsa --exceptions examples/exceptions/exclude-kube-namespaces.json ``` #### Scan Helm charts - Render the helm chart using [`helm template`](https://helm.sh/docs/helm/helm_template/) and pass to stdout @@ -175,6 +177,8 @@ helm template bitnami/mysql --generate-name --dry-run | kubescape scan framework ### Offline Support +[Video tutorial](https://youtu.be/IGXL9s37smM) + It is possible to run Kubescape offline! First download the framework and then scan with `--use-from` flag diff --git a/cautils/customerloader.go b/cautils/customerloader.go index 872aaf64..6bbacf0a 100644 --- a/cautils/customerloader.go +++ b/cautils/customerloader.go @@ -131,7 +131,7 @@ func (c *EmptyConfig) GetDefaultNS() string { return k8sinterf func (c *EmptyConfig) GetBackendAPI() getter.IBackend { return nil } // TODO: return mock obj func (c *EmptyConfig) GetClusterName() string { return adoptClusterName(k8sinterface.GetClusterName()) } func (c *EmptyConfig) GenerateURL() { - message := fmt.Sprintf("\nCheckout for more cool features: https://%s\n", getter.GetArmoAPIConnector().GetFrontendURL()) + message := fmt.Sprintf("\nYou 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 registering here: https://%s\n", getter.GetArmoAPIConnector().GetFrontendURL()) InfoTextDisplay(os.Stdout, fmt.Sprintf("\n%s\n", message)) } @@ -161,7 +161,7 @@ func (c *ClusterConfig) GetDefaultNS() string { return c.defau func (c *ClusterConfig) GetBackendAPI() getter.IBackend { return c.backendAPI } func (c *ClusterConfig) GenerateURL() { - message := "Checkout for more cool features: " + message := "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 registering here: " u := url.URL{} u.Scheme = "https" diff --git a/cautils/scaninfo.go b/cautils/scaninfo.go index 9a678aa9..02f667b2 100644 --- a/cautils/scaninfo.go +++ b/cautils/scaninfo.go @@ -1,8 +1,6 @@ package cautils import ( - "io" - "os" "path/filepath" "github.com/armosec/kubescape/cautils/getter" @@ -69,24 +67,6 @@ func (scanInfo *ScanInfo) setUseFrom() { } } -func (scanInfo *ScanInfo) SetInputPatterns(args []string) error { - if args[1] != "-" { - scanInfo.InputPatterns = args[1:] - } else { // store stout to file - 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()} - } - return nil -} - func (scanInfo *ScanInfo) setOutputFile() { if scanInfo.Output == "" { return @@ -107,20 +87,20 @@ func (scanInfo *ScanInfo) ScanRunningCluster() bool { return len(scanInfo.InputPatterns) == 0 } -func (scanInfo *ScanInfo) SetPolicyIdentifierForGivenFrameworks(frameworks []string) { - for _, framework := range frameworks { - if !scanInfo.contains(framework) { +func (scanInfo *ScanInfo) SetPolicyIdentifiers(policies []string, kind reporthandling.NotificationPolicyKind) { + for _, policy := range policies { + if !scanInfo.contains(policy) { newPolicy := reporthandling.PolicyIdentifier{} - newPolicy.Kind = reporthandling.KindFramework - newPolicy.Name = framework + newPolicy.Kind = kind // reporthandling.KindFramework + newPolicy.Name = policy scanInfo.PolicyIdentifier = append(scanInfo.PolicyIdentifier, newPolicy) } } } -func (scanInfo *ScanInfo) contains(framework string) bool { +func (scanInfo *ScanInfo) contains(policyName string) bool { for _, policy := range scanInfo.PolicyIdentifier { - if policy.Name == framework { + if policy.Name == policyName { return true } } diff --git a/clihandler/cmd/control.go b/clihandler/cmd/control.go index df120324..a0772767 100644 --- a/clihandler/cmd/control.go +++ b/clihandler/cmd/control.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "io" "os" "strings" @@ -21,7 +22,7 @@ var controlCmd = &cobra.Command{ controls := strings.Split(args[0], ",") if len(controls) > 1 { if controls[1] == "" { - return fmt.Errorf("usage: ,") + return fmt.Errorf("usage: ,") } } } else { @@ -34,23 +35,31 @@ var controlCmd = &cobra.Command{ scanInfo.PolicyIdentifier = []reporthandling.PolicyIdentifier{} if len(args) == 0 { - scanInfo.SetPolicyIdentifierForGivenFrameworks(getter.NativeFrameworks) - } else { - controls := strings.Split(args[0], ",") - scanInfo.PolicyIdentifier = []reporthandling.PolicyIdentifier{} - scanInfo.PolicyIdentifier = setScanForFirstControl(controls) + scanInfo.SetPolicyIdentifiers(getter.NativeFrameworks, reporthandling.KindFramework) + scanInfo.ScanAll = true + } else { // expected control or list of control sepparated by "," - if len(controls) > 1 { - scanInfo.PolicyIdentifier = SetScanForGivenControls(controls[1:]) - } + // Read controls from input args + scanInfo.SetPolicyIdentifiers(strings.Split(args[0], ","), reporthandling.KindControl) if len(args) > 1 { - // Set scan to run on yamls - if err := scanInfo.SetInputPatterns(args); err != nil { - return err + 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 = false scanInfo.Init() cautils.SetSilentMode(scanInfo.Silent) diff --git a/clihandler/cmd/framework.go b/clihandler/cmd/framework.go index 3d56cb36..e381ecff 100644 --- a/clihandler/cmd/framework.go +++ b/clihandler/cmd/framework.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "io" "os" "strings" @@ -18,34 +19,48 @@ var frameworkCmd = &cobra.Command{ Long: "Execute a scan on a running Kubernetes cluster or `yaml`/`json` files (use glob) or `-` for stdin", ValidArgs: getter.NativeFrameworks, Args: func(cmd *cobra.Command, args []string) error { - if len(args) == 0 { + if len(args) > 0 { + frameworks := strings.Split(args[0], ",") + if len(frameworks) > 1 { + if frameworks[1] == "" { + return fmt.Errorf("usage: ,") + } + } + } else { return fmt.Errorf("requires at least one framework name") } return nil }, RunE: func(cmd *cobra.Command, args []string) error { flagValidationFramework() - scanInfo.PolicyIdentifier = []reporthandling.PolicyIdentifier{} - // If no framework provided, use all - if len(args) == 0 { - scanInfo.SetPolicyIdentifierForGivenFrameworks(getter.NativeFrameworks) + var frameworks []string + + if len(args) == 0 { // scan all frameworks + frameworks = getter.NativeFrameworks scanInfo.ScanAll = true } else { // Read frameworks from input args - scanInfo.PolicyIdentifier = []reporthandling.PolicyIdentifier{} - frameworks := strings.Split(strings.Join(strings.Fields(args[0]), ""), ",") - scanInfo.PolicyIdentifier = SetScanForFirstFramework(frameworks) - if len(frameworks) > 1 { - scanInfo.SetPolicyIdentifierForGivenFrameworks(frameworks[1:]) - } + frameworks = strings.Split(args[0], ",") if len(args) > 1 { - // expected yaml/url input - if err := scanInfo.SetInputPatterns(args); err != nil { - return err + 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.SetPolicyIdentifiers(frameworks, reporthandling.KindFramework) + scanInfo.Init() cautils.SetSilentMode(scanInfo.Silent) err := clihandler.ScanCliSetup(&scanInfo) @@ -62,13 +77,13 @@ func init() { scanInfo.FrameworkScan = true } -func SetScanForFirstFramework(frameworks []string) []reporthandling.PolicyIdentifier { - newPolicy := reporthandling.PolicyIdentifier{} - newPolicy.Kind = reporthandling.KindFramework - newPolicy.Name = frameworks[0] - scanInfo.PolicyIdentifier = append(scanInfo.PolicyIdentifier, newPolicy) - return scanInfo.PolicyIdentifier -} +// func SetScanForFirstFramework(frameworks []string) []reporthandling.PolicyIdentifier { +// newPolicy := reporthandling.PolicyIdentifier{} +// newPolicy.Kind = reporthandling.KindFramework +// newPolicy.Name = frameworks[0] +// scanInfo.PolicyIdentifier = append(scanInfo.PolicyIdentifier, newPolicy) +// return scanInfo.PolicyIdentifier +// } func flagValidationFramework() { if scanInfo.Submit && scanInfo.Local { diff --git a/clihandler/initcli.go b/clihandler/initcli.go index fb6acc9a..f74dac57 100644 --- a/clihandler/initcli.go +++ b/clihandler/initcli.go @@ -101,9 +101,10 @@ func setPolicyGetter(scanInfo *cautils.ScanInfo, customerGUID string) { if scanInfo.ScanAll { frameworks, err := g.ListCustomFrameworks(customerGUID) if err != nil { - glog.Error("could not get custom frameworks") + glog.Error("failed to get custom frameworks") // handle error + return } - scanInfo.SetPolicyIdentifierForGivenFrameworks(frameworks) + scanInfo.SetPolicyIdentifiers(frameworks, reporthandling.KindFramework) } } } diff --git a/docs/run-options.md b/docs/run-options.md index 9233f49b..f2e0adf2 100644 --- a/docs/run-options.md +++ b/docs/run-options.md @@ -25,7 +25,7 @@ kubescape scan framework nsa --exclude-namespaces kube-system,kube-public ### Examples -* Scan a running Kubernetes cluster with [`nsa`](https://www.nsa.gov/News-Features/Feature-Stories/Article-View/Article/2716980/nsa-cisa-release-kubernetes-hardening-guidance/) framework +* Scan a running Kubernetes cluster with [`nsa`](https://www.nsa.gov/Press-Room/News-Highlights/Article/Article/2716980/nsa-cisa-release-kubernetes-hardening-guidance/) framework ``` kubescape scan framework nsa --exclude-namespaces kube-system,kube-public ``` diff --git a/examples/exceptions/README.md b/examples/exceptions/README.md new file mode 100644 index 00000000..4fd13019 --- /dev/null +++ b/examples/exceptions/README.md @@ -0,0 +1,179 @@ +# Kubescape Exceptions + +Kubescape Exceptions is the proper way of excluding failed resources from effecting the risk score. + +e.g. When a `kube-system` resource fails and it is ok, simply add the resource to the exceptions configurations. + +## Definitions + + +* `name`- Exception name - unique name representing the exception +* `policyType`- Do not change +* `actions`- List of available actions. Currently alertOnly is supported +* `resources`- List of resources to apply this exception on + * `designatorType: Attributes`- An attribute-based declaration {key: value} + Supported keys: + * `name`: k8s resource name (case-sensitive, regex supported) + * `kind`: k8s resource kind (case-sensitive, regex supported) + * `namespace`: k8s resource namespace (case-sensitive, regex supported) + * `cluster`: k8s cluster name (usually it is the `current-context`) (case-sensitive, regex supported) + * resource labels as key value (case-sensitive, regex NOT supported) +* `posturePolicies`- An attribute-based declaration {key: value} + * `frameworkName` - Framework names can be find [here](https://github.com/armosec/regolibrary/tree/master/frameworks) + * `controlName` - Control names can be find [here](https://github.com/armosec/regolibrary/tree/master/controls) + * `controlID` - Not yet supported + * `ruleName` - Rule names can be find [here](https://github.com/armosec/regolibrary/tree/master/rules) + + +## Usage + +The `resources` list and `posturePolicies` list are design to be a combination of the resources and policies to exclude +> You must declare at least one resource and one policy + +e.g. If you wish to exclude all namespaces with the label `"environment": "dev"`, the resource list should look as following: +``` +"resources": [ + { + "designatorType": "Attributes", + "attributes": { + "namespace": ".*", + "environment": "dev" + } + } +] +``` + +But if you wish to exclude all namespaces **OR** any resource with the label `"environment": "dev"`, the resource list should look as following: +``` +"resources": [ + { + "designatorType": "Attributes", + "attributes": { + "namespace": ".*" + } + }, + { + "designatorType": "Attributes", + "attributes": { + "environment": "dev" + } + } +] +``` + +Same works with the `posturePolicies` list -> + +e.g. If you wish to exclude the resources declared in the `resources` list that failed when scanning the `NSA` framework **AND** failed the `Allowed hostPath` control, the `posturePolicies` list should look as following: +``` +"posturePolicies": [ + { + "frameworkName": "NSA", + "controlName": "Allowed hostPath" + } +] +``` + +But if you wish to exclude the resources declared in the `resources` list that failed when scanning the `NSA` framework **OR** failed the `Allowed hostPath` control, the `posturePolicies` list should look as following: +``` +"posturePolicies": [ + { + "frameworkName": "NSA" + }, + { + "controlName": "Allowed hostPath" + } +] +``` + +## Examples + +Here are some examples demonstrating the different ways the exceptions file can be configured + + +### Exclude control + +Exclude the ["Allowed hostPath" control](https://github.com/armosec/regolibrary/blob/master/controls/allowedhostpath.json#L2) by declaring the control in the `"posturePolicies"` section. + +The resources + +``` +[ + { + "name": "exclude-allowed-hostPath-control", + "policyType": "postureExceptionPolicy", + "actions": [ + "alertOnly" + ], + "resources": [ + { + "designatorType": "Attributes", + "attributes": { + "kind": ".*" + } + } + ], + "posturePolicies": [ + { + "controlName": "Allowed hostPath" + } + ] + } +] +``` + +### Exclude deployments in the default namespace that failed the "Allowed hostPath" control +``` +[ + { + "name": "exclude-deployments-in-ns-default", + "policyType": "postureExceptionPolicy", + "actions": [ + "alertOnly" + ], + "resources": [ + { + "designatorType": "Attributes", + "attributes": { + "namespace": "default", + "kind": "Deployment" + } + } + ], + "posturePolicies": [ + { + "controlName": "Allowed hostPath" + } + ] + } +] +``` + +### Exclude resources with label "app=nginx" running in a minikube cluster that failed the "NSA" or "MITRE" framework +``` +[ + { + "name": "exclude-nginx-minikube", + "policyType": "postureExceptionPolicy", + "actions": [ + "alertOnly" + ], + "resources": [ + { + "designatorType": "Attributes", + "attributes": { + "cluster": "minikube", + "app": "nginx" + } + } + ], + "posturePolicies": [ + { + "frameworkName": "NSA" + }, + { + "frameworkName": "MITRE" + } + ] + } +] +``` \ No newline at end of file diff --git a/examples/exceptions/exclude-allowed-hostPath-control.json b/examples/exceptions/exclude-allowed-hostPath-control.json new file mode 100644 index 00000000..106dfaa6 --- /dev/null +++ b/examples/exceptions/exclude-allowed-hostPath-control.json @@ -0,0 +1,22 @@ +[ + { + "name": "exclude-allowed-hostPath-control", + "policyType": "postureExceptionPolicy", + "actions": [ + "alertOnly" + ], + "resources": [ + { + "designatorType": "Attributes", + "attributes": { + "kind": ".*" + } + } + ], + "posturePolicies": [ + { + "controlName": "Allowed hostPath" + } + ] + } +] \ No newline at end of file diff --git a/examples/exceptions/exclude-deployments-in-ns-default.json b/examples/exceptions/exclude-deployments-in-ns-default.json new file mode 100644 index 00000000..dceb4010 --- /dev/null +++ b/examples/exceptions/exclude-deployments-in-ns-default.json @@ -0,0 +1,23 @@ +[ + { + "name": "exclude-deployments-in-ns-default", + "policyType": "postureExceptionPolicy", + "actions": [ + "alertOnly" + ], + "resources": [ + { + "designatorType": "Attributes", + "attributes": { + "namespace": "default", + "kind": "Deployment" + } + } + ], + "posturePolicies": [ + { + "controlName": "Allowed hostPath" + } + ] + } +] \ No newline at end of file diff --git a/examples/exceptions.json b/examples/exceptions/exclude-kube-namespaces.json similarity index 85% rename from examples/exceptions.json rename to examples/exceptions/exclude-kube-namespaces.json index 7f67a52b..a8aecd4a 100644 --- a/examples/exceptions.json +++ b/examples/exceptions/exclude-kube-namespaces.json @@ -28,6 +28,12 @@ "posturePolicies": [ { "frameworkName": "NSA" + }, + { + "frameworkName": "MITRE" + }, + { + "frameworkName": "ArmoBest" } ] } diff --git a/examples/exceptions/exclude-nginx-in-minikube.json b/examples/exceptions/exclude-nginx-in-minikube.json new file mode 100644 index 00000000..c0e3cdfe --- /dev/null +++ b/examples/exceptions/exclude-nginx-in-minikube.json @@ -0,0 +1,26 @@ +[ + { + "name": "exclude-nginx-in-minikube", + "policyType": "postureExceptionPolicy", + "actions": [ + "alertOnly" + ], + "resources": [ + { + "designatorType": "Attributes", + "attributes": { + "cluster": "minikube", + "app": "nginx" + } + } + ], + "posturePolicies": [ + { + "frameworkName": "NSA" + }, + { + "frameworkName": "MITRE" + } + ] + } +] \ No newline at end of file diff --git a/go.mod b/go.mod index 6567897a..ac553962 100644 --- a/go.mod +++ b/go.mod @@ -3,9 +3,9 @@ module github.com/armosec/kubescape go 1.17 require ( - github.com/armosec/armoapi-go v0.0.8 + github.com/armosec/armoapi-go v0.0.23 github.com/armosec/k8s-interface v0.0.8 - github.com/armosec/opa-utils v0.0.39 + github.com/armosec/opa-utils v0.0.42 github.com/armosec/rbac-utils v0.0.1 github.com/armosec/utils-go v0.0.3 github.com/briandowns/spinner v1.16.0 diff --git a/go.sum b/go.sum index c5a8c3df..d298636d 100644 --- a/go.sum +++ b/go.sum @@ -84,13 +84,12 @@ github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5 github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armosec/armoapi-go v0.0.2/go.mod h1:vIK17yoKbJRQyZXWWLe3AqfqCRITxW8qmSkApyq5xFs= -github.com/armosec/armoapi-go v0.0.7/go.mod h1:iaVVGyc23QGGzAdv4n+szGQg3Rbpixn9yQTU3qWRpaw= -github.com/armosec/armoapi-go v0.0.8 h1:JPa9rZynuE2RucamDh6dsy/sjCScmWDsyt1zagJFCDo= -github.com/armosec/armoapi-go v0.0.8/go.mod h1:iaVVGyc23QGGzAdv4n+szGQg3Rbpixn9yQTU3qWRpaw= +github.com/armosec/armoapi-go v0.0.23 h1:jqoLIWM5CR7DCD9fpFgN0ePqtHvOCoZv/XzCwsUluJU= +github.com/armosec/armoapi-go v0.0.23/go.mod h1:iaVVGyc23QGGzAdv4n+szGQg3Rbpixn9yQTU3qWRpaw= github.com/armosec/k8s-interface v0.0.8 h1:Eo3Qen4yFXxzVem49FNeij2ckyzHSAJ0w6PZMaSEIm8= github.com/armosec/k8s-interface v0.0.8/go.mod h1:xxS+V5QT3gVQTwZyAMMDrYLWGrfKOpiJ7Jfhfa0w9sM= -github.com/armosec/opa-utils v0.0.39 h1:YOPMmwZaseqZT2/io918YycrMoJYu+ggbINnZJR9ZUA= -github.com/armosec/opa-utils v0.0.39/go.mod h1:JaE2a0kB2O22JZCqBBfOS9Pvh9rXs9xXXb9lVo01rTs= +github.com/armosec/opa-utils v0.0.42 h1:7YzQJNVBmM0+1nWOAiUgDt+mvlVEwApg80FjMh4oxXo= +github.com/armosec/opa-utils v0.0.42/go.mod h1:OqewZoSqKD5udtQ4lGFixb8yyFNqLq9zqinlAL6KSjM= github.com/armosec/rbac-utils v0.0.1 h1:N2MI98F/0zbDjmRZ29CNElU1AXkFLk5csd/qAHOBdXY= github.com/armosec/rbac-utils v0.0.1/go.mod h1:pQ8CBiij8kSKV7aeZm9FMvtZN28VgA7LZcYyTWimq40= github.com/armosec/utils-go v0.0.2/go.mod h1:itWmRLzRdsnwjpEOomL0mBWGnVNNIxSjDAdyc+b0iUo= diff --git a/smoke_testing/smoke_utils.py b/smoke_testing/smoke_utils.py index 7b56349e..3bff46d9 100644 --- a/smoke_testing/smoke_utils.py +++ b/smoke_testing/smoke_utils.py @@ -7,7 +7,13 @@ def get_exec_from_args(args: list): def run_command(command): try: - return f"{subprocess.check_output(command, stderr=subprocess.STDOUT)}" + return f"{subprocess.check_output(command, stdin=subprocess.PIPE, stderr=subprocess.STDOUT)}" except Exception as e: return f"{e}" + +def assertion(msg): + errors = ["Error: invalid parameter", "exit status 1"] + for e in errors: + assert e not in msg, msg + diff --git a/smoke_testing/test_scan.py b/smoke_testing/test_scan.py index d886d0da..0e18fb8a 100644 --- a/smoke_testing/test_scan.py +++ b/smoke_testing/test_scan.py @@ -3,15 +3,72 @@ import smoke_utils import sys -def full_scan(kubescape_exec: str): - return smoke_utils.run_command(command=[kubescape_exec, "scan", "framework", "nsa", os.path.join("..", "*.yaml")]) +all_files = os.path.join("..", "*.yaml") +# all_files = os.path.join("..", "examples", "online-boutique", "*.yaml") +single_file = os.path.join("..", "examples", "online-boutique", "frontend.yaml") + + +def scan_all(kubescape_exec: str): + return smoke_utils.run_command(command=[kubescape_exec, "scan", all_files]) + + +def scan_control_name(kubescape_exec: str): + return smoke_utils.run_command(command=[kubescape_exec, "scan", "control", 'Allowed hostPath', all_files]) + + +def scan_control_id(kubescape_exec: str): + return smoke_utils.run_command(command=[kubescape_exec, "scan", "control", 'C-0006', all_files]) + + +def scan_controls(kubescape_exec: str): + return smoke_utils.run_command(command=[kubescape_exec, "scan", "control", 'Allowed hostPath,Allow privilege escalation', all_files]) + + +def scan_framework(kubescape_exec: str): + return smoke_utils.run_command(command=[kubescape_exec, "scan", "framework", "nsa", all_files]) + + +def scan_frameworks(kubescape_exec: str): + return smoke_utils.run_command(command=[kubescape_exec, "scan", "framework", "nsa,mitre,armobest", all_files]) + + +def scan_from_stdin(kubescape_exec: str): + return smoke_utils.run_command(command=["cat", single_file, "|", kubescape_exec, "scan", "framework", "nsa", "-"]) def run(kubescape_exec: str): - # return - print("Testing E2E yaml files") - msg = full_scan(kubescape_exec=kubescape_exec) - assert "exit status 1" not in msg, msg + print("Testing E2E on yaml files") + + # TODO - fix support + # print("Testing scan all yaml files") + # msg = scan_all(kubescape_exec=kubescape_exec) + # smoke_utils.assertion(msg) + + print("Testing scan control name") + msg = scan_control_name(kubescape_exec=kubescape_exec) + smoke_utils.assertion(msg) + + print("Testing scan control id") + msg = scan_control_id(kubescape_exec=kubescape_exec) + smoke_utils.assertion(msg) + + print("Testing scan controls") + msg = scan_controls(kubescape_exec=kubescape_exec) + smoke_utils.assertion(msg) + + print("Testing scan framework") + msg = scan_framework(kubescape_exec=kubescape_exec) + smoke_utils.assertion(msg) + + print("Testing scan frameworks") + msg = scan_frameworks(kubescape_exec=kubescape_exec) + smoke_utils.assertion(msg) + + # TODO - fix test + # print("Testing scan from stdin") + # msg = scan_from_stdin(kubescape_exec=kubescape_exec) + # smoke_utils.assertion(msg) + print("Done E2E yaml files")