2019-12-02 15:40:44 +00:00
package cmd
import (
"fmt"
"os"
"path/filepath"
"strings"
"github.com/aquasecurity/kube-bench/check"
"github.com/golang/glog"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
func init ( ) {
RootCmd . AddCommand ( runCmd )
2019-12-05 20:55:44 +00:00
runCmd . Flags ( ) . StringSliceP ( "targets" , "s" , [ ] string { } ,
` Specify targets of the benchmark to run . These names need to match the filenames in the cfg / < version > directory .
2020-08-30 07:16:21 +00:00
For example , to run the tests specified in master . yaml and etcd . yaml , specify -- targets = master , etcd
2019-12-05 20:55:44 +00:00
If no targets are specified , run tests from all files in the cfg / < version > directory .
2019-12-02 15:40:44 +00:00
` )
}
// runCmd represents the run command
var runCmd = & cobra . Command {
Use : "run" ,
Short : "Run tests" ,
Long : ` Run tests. If no arguments are specified, runs tests from all files ` ,
Run : func ( cmd * cobra . Command , args [ ] string ) {
2019-12-05 20:55:44 +00:00
targets , err := cmd . Flags ( ) . GetStringSlice ( "targets" )
2019-12-02 15:40:44 +00:00
if err != nil {
2019-12-13 16:04:58 +00:00
exitWithError ( fmt . Errorf ( "unable to get `targets` from command line :%v" , err ) )
2019-12-02 15:40:44 +00:00
}
2022-01-10 13:25:15 +00:00
bv , err := getBenchmarkVersion ( kubeVersion , benchmarkVersion , getPlatformInfo ( ) , viper . GetViper ( ) )
2019-12-02 15:40:44 +00:00
if err != nil {
2019-12-13 16:04:58 +00:00
exitWithError ( fmt . Errorf ( "unable to get benchmark version. error: %v" , err ) )
2019-12-02 15:40:44 +00:00
}
2020-08-30 07:16:21 +00:00
glog . V ( 2 ) . Infof ( "Checking targets %v for %v" , targets , bv )
benchmarkVersionToTargetsMap , err := loadTargetMapping ( viper . GetViper ( ) )
if err != nil {
exitWithError ( fmt . Errorf ( "error loading targets: %v" , err ) )
}
valid , err := validTargets ( bv , targets , viper . GetViper ( ) )
if err != nil {
exitWithError ( fmt . Errorf ( "error validating targets: %v" , err ) )
}
if len ( targets ) > 0 && ! valid {
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 ] ) ) )
2019-12-05 20:55:44 +00:00
}
2019-12-02 15:40:44 +00:00
// Merge version-specific config if any.
2020-08-30 07:16:21 +00:00
path := filepath . Join ( cfgDir , bv )
2021-02-23 14:22:15 +00:00
err = mergeConfig ( path )
if err != nil {
2022-01-23 07:40:59 +00:00
exitWithError ( fmt . Errorf ( "Error in mergeConfig: %v\n" , err ) )
2021-02-23 14:22:15 +00:00
}
2019-12-02 15:40:44 +00:00
2020-08-30 07:16:21 +00:00
err = run ( targets , bv )
2019-12-02 15:40:44 +00:00
if err != nil {
2022-01-23 07:40:59 +00:00
exitWithError ( fmt . Errorf ( "Error in run: %v\n" , err ) )
2019-12-02 15:40:44 +00:00
}
2022-01-23 07:40:59 +00:00
os . Exit ( exitCodeSelection ( controlsCollection ) )
2019-12-02 15:40:44 +00:00
} ,
}
2019-12-05 20:55:44 +00:00
func run ( targets [ ] string , benchmarkVersion string ) ( err error ) {
yamlFiles , err := getTestYamlFiles ( targets , benchmarkVersion )
2019-12-02 15:40:44 +00:00
if err != nil {
return err
}
glog . V ( 3 ) . Infof ( "Running tests from files %v\n" , yamlFiles )
for _ , yamlFile := range yamlFiles {
_ , name := filepath . Split ( yamlFile )
testType := check . NodeType ( strings . Split ( name , "." ) [ 0 ] )
2021-05-09 11:48:34 +00:00
runChecks ( testType , yamlFile , detecetedKubeVersion )
2019-12-02 15:40:44 +00:00
}
2020-06-24 09:13:10 +00:00
writeOutput ( controlsCollection )
2019-12-02 15:40:44 +00:00
return nil
}
2019-12-05 20:55:44 +00:00
func getTestYamlFiles ( targets [ ] string , benchmarkVersion string ) ( yamlFiles [ ] string , err error ) {
// Check that the specified targets have corresponding YAML files in the config directory
2019-12-02 15:40:44 +00:00
configFileDirectory := filepath . Join ( cfgDir , benchmarkVersion )
2019-12-05 20:55:44 +00:00
for _ , target := range targets {
filename := translate ( target ) + ".yaml"
2019-12-02 15:40:44 +00:00
file := filepath . Join ( configFileDirectory , filename )
if _ , err := os . Stat ( file ) ; err != nil {
return nil , fmt . Errorf ( "file %s not found for version %s" , filename , benchmarkVersion )
}
yamlFiles = append ( yamlFiles , file )
}
2019-12-05 20:55:44 +00:00
// If no targets were specified, we will run tests from all the files in the directory
2019-12-02 15:40:44 +00:00
if len ( yamlFiles ) == 0 {
yamlFiles , err = getYamlFilesFromDir ( configFileDirectory )
if err != nil {
return nil , err
}
}
return yamlFiles , err
}
2019-12-05 20:55:44 +00:00
func translate ( target string ) string {
return strings . Replace ( strings . ToLower ( target ) , "worker" , "node" , - 1 )
}