fixed stdin support

This commit is contained in:
dwertent
2021-11-16 15:57:23 +02:00
parent fea84c9652
commit b7a51a2495
7 changed files with 142 additions and 75 deletions

View File

@@ -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
}
}

View File

@@ -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: <control_one>,<control_two>")
return fmt.Errorf("usage: <control-0>,<control-1>")
}
}
} 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)

View File

@@ -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: <framework-0>,<framework-1>")
}
}
} 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 {

View File

@@ -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)
}
}
}

View File

@@ -27,10 +27,10 @@ e.g. When a `kube-system` resource fails and it is ok, simply add the resource t
## Usage
The `resources` list and `posturePolicies` list are design to be a combination of the resources sand policies to exclude
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:
e.g. If you wish to exclude all namespaces with the label `"environment": "dev"`, the resource list should look as following:
```
"resources": [
{
@@ -43,7 +43,7 @@ e.g. If you wish to exclude all namespaces with the label "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:
But if you wish to exclude all namespaces **OR** any resource with the label `"environment": "dev"`, the resource list should look as following:
```
"resources": [
{
@@ -63,17 +63,17 @@ But if you wish to exclude all namespaces **OR** any resource with the label "en
Same works with the `posturePolicies` list ->
e.g. If you wish to exclude the resources decleared in the `resources` list that faild when scanning the `NSA` framework **AND** failed the `Allowed hostPath` control, the `posturePolicies` list should look as following:
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"
"frameworkName": "NSA",
"controlName": "Allowed hostPath"
}
]
```
But if you wish to exclude the resources decleared in the `resources` list that faild when scanning the `NSA` framework **OR** failed the `Allowed hostPath` control, the `posturePolicies` list should look as following:
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": [
{

View File

@@ -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

View File

@@ -3,15 +3,71 @@ 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("..", "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")