github.com/castai/kvisor@v1.7.1-0.20240516114728-b3572a2607b5/cmd/linter/kubebench/run.go (about)

     1  package kubebench
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"strings"
     8  
     9  	check "github.com/castai/kvisor/cmd/linter/kubebench/check"
    10  	"github.com/golang/glog"
    11  	"github.com/spf13/cobra"
    12  	"github.com/spf13/viper"
    13  )
    14  
    15  func NewRunCommand() *cobra.Command {
    16  	cmd := &cobra.Command{
    17  		Use:   "run",
    18  		Short: "Run kube-bench tests",
    19  		Run: func(cmd *cobra.Command, args []string) {
    20  			targets, err := cmd.Flags().GetStringSlice("targets")
    21  			if err != nil {
    22  				exitWithError(fmt.Errorf("unable to get `targets` from command line :%v", err))
    23  			}
    24  
    25  			bv, err := getBenchmarkVersion(kubeVersion, benchmarkVersion, getPlatformInfo(), viper.GetViper())
    26  			if err != nil {
    27  				exitWithError(fmt.Errorf("unable to get benchmark version. error: %v", err))
    28  			}
    29  
    30  			glog.V(2).Infof("Checking targets %v for %v", targets, bv)
    31  			benchmarkVersionToTargetsMap, err := loadTargetMapping(viper.GetViper())
    32  			if err != nil {
    33  				exitWithError(fmt.Errorf("error loading targets: %v", err))
    34  			}
    35  			valid, err := validTargets(bv, targets, viper.GetViper())
    36  			if err != nil {
    37  				exitWithError(fmt.Errorf("error validating targets: %v", err))
    38  			}
    39  			if len(targets) > 0 && !valid {
    40  				exitWithError(fmt.Errorf(fmt.Sprintf(`The specified --targets "%s" are not configured for the CIS Benchmark %s\n Valid targets %v`, strings.Join(targets, ","), bv, benchmarkVersionToTargetsMap[bv])))
    41  			}
    42  
    43  			// Merge version-specific config if any.
    44  			path := filepath.Join(cfgDir, bv)
    45  			err = mergeConfig(path)
    46  			if err != nil {
    47  				exitWithError(fmt.Errorf("Error in mergeConfig: %v\n", err))
    48  			}
    49  
    50  			err = run(targets, bv)
    51  			if err != nil {
    52  				exitWithError(fmt.Errorf("Error in run: %v\n", err))
    53  			}
    54  
    55  			os.Exit(exitCodeSelection(controlsCollection))
    56  		},
    57  	}
    58  	cmd.Flags().StringSliceP("targets", "s", []string{},
    59  		`Specify targets of the benchmark to run. These names need to match the filenames in the cfg/<version> directory.
    60  	For example, to run the tests specified in master.yaml and etcd.yaml, specify --targets=master,etcd
    61  	If no targets are specified, run tests from all files in the cfg/<version> directory.
    62  	`)
    63  
    64  	return cmd
    65  }
    66  
    67  func run(targets []string, benchmarkVersion string) (err error) {
    68  	yamlFiles, err := getTestYamlFiles(targets, benchmarkVersion)
    69  	if err != nil {
    70  		return err
    71  	}
    72  
    73  	glog.V(3).Infof("Running tests from files %v\n", yamlFiles)
    74  
    75  	for _, yamlFile := range yamlFiles {
    76  		_, name := filepath.Split(yamlFile)
    77  		testType := check.NodeType(strings.Split(name, ".")[0])
    78  		runChecks(testType, yamlFile, detecetedKubeVersion)
    79  	}
    80  
    81  	writeOutput(controlsCollection)
    82  	return nil
    83  }
    84  
    85  func getTestYamlFiles(targets []string, benchmarkVersion string) (yamlFiles []string, err error) {
    86  	// Check that the specified targets have corresponding YAML files in the config directory
    87  	configFileDirectory := filepath.Join(cfgDir, benchmarkVersion)
    88  	for _, target := range targets {
    89  		filename := translate(target) + ".yaml"
    90  		file := filepath.Join(configFileDirectory, filename)
    91  		if _, err := os.Stat(file); err != nil {
    92  			return nil, fmt.Errorf("file %s not found for version %s", filename, benchmarkVersion)
    93  		}
    94  		yamlFiles = append(yamlFiles, file)
    95  	}
    96  
    97  	// If no targets were specified, we will run tests from all the files in the directory
    98  	if len(yamlFiles) == 0 {
    99  		yamlFiles, err = getYamlFilesFromDir(configFileDirectory)
   100  		if err != nil {
   101  			return nil, err
   102  		}
   103  	}
   104  
   105  	return yamlFiles, err
   106  }
   107  
   108  func translate(target string) string {
   109  	return strings.Replace(strings.ToLower(target), "worker", "node", -1)
   110  }