github.com/khulnasoft-lab/kube-bench@v0.2.1-0.20240330183753-9df52345ae58/cmd/run.go (about)

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