Skip to content
Snippets Groups Projects
Select Git revision
  • 64aaef799716768ee15e3089347d2c22a2a0585c
  • main default protected
  • lihiz_preflight
  • release/prepare-v0.10.7
  • dependabot/github_actions/golangci/golangci-lint-action-7
  • release/prepare-v0.9.1
  • gh-pages
  • aquadev
  • v0.11.1
  • v0.11.0
  • v0.10.7
  • v0.10.6
  • v0.10.5
  • v0.10.4
  • v0.10.3
  • v0.10.2
  • v0.10.1
  • v0.10.0
  • v0.9.4
  • v0.9.3
  • v0.9.2
  • v0.9.1
  • v0.9.0
  • v0.8.0
  • v0.7.3
  • v0.7.2
  • v0.7.1
  • v0.7.0
28 results

common.go

Blame
  • user avatar
    Abubakr-Sadik Nii Nai Davis authored
    64aaef79
    History
    common.go 4.57 KiB
    // Copyright © 2017 Aqua Security Software Ltd. <info@aquasec.com>
    //
    // Licensed under the Apache License, Version 2.0 (the "License");
    // you may not use this file except in compliance with the License.
    // You may obtain a copy of the License at
    //
    //     http://www.apache.org/licenses/LICENSE-2.0
    //
    // Unless required by applicable law or agreed to in writing, software
    // distributed under the License is distributed on an "AS IS" BASIS,
    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    // See the License for the specific language governing permissions and
    // limitations under the License.
    
    package cmd
    
    import (
    	"fmt"
    	"io/ioutil"
    
    	"github.com/aquasecurity/kube-bench/check"
    	"github.com/golang/glog"
    	"github.com/spf13/viper"
    )
    
    var (
    	errmsgs string
    )
    
    func runChecks(t check.NodeType) {
    	var summary check.Summary
    	var nodetype string
    	var file string
    	var err error
    	var typeConf *viper.Viper
    
    	switch t {
    	case check.MASTER:
    		file = masterFile
    		nodetype = "master"
    	case check.NODE:
    		file = nodeFile
    		nodetype = "node"
    	case check.FEDERATED:
    		file = federatedFile
    		nodetype = "federated"
    	}
    
    	ver := getKubeVersion()
    	path := fmt.Sprintf("%s/%s", cfgDir, ver)
    
    	def := fmt.Sprintf("%s/%s", path, file)
    	in, err := ioutil.ReadFile(def)
    	if err != nil {
    		exitWithError(fmt.Errorf("error opening %s controls file: %v", t, err))
    	}
    
    	// Merge kubernetes version specific config if any.
    	viper.SetConfigFile(path + "/config.yaml")
    	err = viper.MergeInConfig()
    	if err != nil {
    		continueWithError(err, fmt.Sprintf("Reading %s specific configuration file", ver))
    	}
    	typeConf = viper.Sub(nodetype)
    
    	// Get the set of exectuables and config files we care about on this type of node. This also
    	// checks that the executables we need for the node type are running.
    	binmap := getBinaries(typeConf)
    	confmap := getConfigFiles(typeConf)
    
    	// Variable substitutions. Replace all occurrences of variables in controls files.
    	s := string(in)
    	s = makeSubstitutions(s, "bin", binmap)
    	s = makeSubstitutions(s, "conf", confmap)
    
    	glog.V(1).Info(fmt.Sprintf("Using config file: %s\n", viper.ConfigFileUsed()))
    	glog.V(1).Info(fmt.Sprintf("Using benchmark file: %s\n", def))
    
    	controls, err := check.NewControls(t, []byte(s))
    	if err != nil {
    		exitWithError(fmt.Errorf("error setting up %s controls: %v", t, err))
    	}
    
    	if groupList != "" && checkList == "" {
    		ids := cleanIDs(groupList)
    		summary = controls.RunGroup(ids...)
    	} else if checkList != "" && groupList == "" {
    		ids := cleanIDs(checkList)
    		summary = controls.RunChecks(ids...)
    	} else if checkList != "" && groupList != "" {
    		exitWithError(fmt.Errorf("group option and check option can't be used together"))
    	} else {
    		summary = controls.RunGroup()
    	}
    
    	// if we successfully ran some tests and it's json format, ignore the warnings
    	if (summary.Fail > 0 || summary.Warn > 0 || summary.Pass > 0) && jsonFmt {
    		out, err := controls.JSON()
    		if err != nil {
    			exitWithError(fmt.Errorf("failed to output in JSON format: %v", err))
    		}
    
    		fmt.Println(string(out))
    	} else {
    		// if we want to store in PostgreSQL, convert to JSON and save it
    		if (summary.Fail > 0 || summary.Warn > 0 || summary.Pass > 0) && pgSql {
    			out, err := controls.JSON()
    			if err != nil {
    				exitWithError(fmt.Errorf("failed to output in JSON format: %v", err))
    			}
    
    			savePgsql(string(out))
    		} else {
    			prettyPrint(controls, summary)
    		}
    	}
    }
    
    // colorPrint outputs the state in a specific colour, along with a message string
    func colorPrint(state check.State, s string) {
    	colors[state].Printf("[%s] ", state)
    	fmt.Printf("%s", s)
    }
    
    // prettyPrint outputs the results to stdout in human-readable format
    func prettyPrint(r *check.Controls, summary check.Summary) {
    	colorPrint(check.INFO, fmt.Sprintf("%s %s\n", r.ID, r.Text))
    	for _, g := range r.Groups {
    		colorPrint(check.INFO, fmt.Sprintf("%s %s\n", g.ID, g.Text))
    		for _, c := range g.Checks {
    			colorPrint(c.State, fmt.Sprintf("%s %s\n", c.ID, c.Text))
    		}
    	}
    
    	fmt.Println()
    
    	// Print remediations.
    	if summary.Fail > 0 || summary.Warn > 0 {
    		colors[check.WARN].Printf("== Remediations ==\n")
    		for _, g := range r.Groups {
    			for _, c := range g.Checks {
    				if c.State != check.PASS {
    					fmt.Printf("%s %s\n", c.ID, c.Remediation)
    				}
    			}
    		}
    		fmt.Println()
    	}
    
    	// Print summary setting output color to highest severity.
    	var res check.State
    	if summary.Fail > 0 {
    		res = check.FAIL
    	} else if summary.Warn > 0 {
    		res = check.WARN
    	} else {
    		res = check.PASS
    	}
    
    	colors[res].Printf("== Summary ==\n")
    	fmt.Printf("%d checks PASS\n%d checks FAIL\n%d checks WARN\n",
    		summary.Pass, summary.Fail, summary.Warn,
    	)
    }