mirror of
https://github.com/aquasecurity/kube-bench.git
synced 2025-07-01 20:32:40 +00:00
* changed error description for missing kubectl/kubelet execs * adds function to generate error message for missing components * adds function to generate error message for missing components * adds function to generate error message for missing components * Update cmd/util.go Co-Authored-By: Liz Rice <liz@lizrice.com> * Update cmd/util.go Co-Authored-By: Liz Rice <liz@lizrice.com> * Update cmd/util.go Co-Authored-By: Liz Rice <liz@lizrice.com> * Update cmd/util.go Co-Authored-By: Liz Rice <liz@lizrice.com> * Update cmd/util.go Co-Authored-By: Liz Rice <liz@lizrice.com> * fixed error message * changes are per PR review
This commit is contained in:
parent
13fe1cdfb8
commit
d5a02f7cb4
@ -81,7 +81,7 @@ func runChecks(nodetype check.NodeType) {
|
|||||||
|
|
||||||
// Get the set of executables and config files we care about on this type of node.
|
// Get the set of executables and config files we care about on this type of node.
|
||||||
typeConf := viper.Sub(string(nodetype))
|
typeConf := viper.Sub(string(nodetype))
|
||||||
binmap, err := getBinaries(typeConf)
|
binmap, err := getBinaries(typeConf, nodetype)
|
||||||
|
|
||||||
// Checks that the executables we need for the node type are running.
|
// Checks that the executables we need for the node type are running.
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -213,7 +213,7 @@ func loadConfig(nodetype check.NodeType) string {
|
|||||||
if kubeVersion == "" {
|
if kubeVersion == "" {
|
||||||
runningVersion, err = getKubeVersion()
|
runningVersion, err = getKubeVersion()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
exitWithError(fmt.Errorf("Version check failed: %s\nAlternatively, you can specify the version with --version", err))
|
exitWithError(fmt.Errorf("Version check failed: \n%s", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -245,7 +245,7 @@ func isMaster() bool {
|
|||||||
glog.V(2).Info("No master components found to be running")
|
glog.V(2).Info("No master components found to be running")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
components, err := getBinariesFunc(masterConf)
|
components, err := getBinariesFunc(masterConf, check.MASTER)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
glog.V(2).Info(err)
|
glog.V(2).Info(err)
|
||||||
|
@ -16,10 +16,11 @@ package cmd
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"testing"
|
||||||
|
|
||||||
"github.com/aquasecurity/kube-bench/check"
|
"github.com/aquasecurity/kube-bench/check"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"testing"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNewRunFilter(t *testing.T) {
|
func TestNewRunFilter(t *testing.T) {
|
||||||
@ -117,13 +118,13 @@ func TestIsMaster(t *testing.T) {
|
|||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
cfgFile string
|
cfgFile string
|
||||||
getBinariesFunc func(*viper.Viper) (map[string]string, error)
|
getBinariesFunc func(*viper.Viper, check.NodeType) (map[string]string, error)
|
||||||
isMaster bool
|
isMaster bool
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
name: "valid config, is master and all components are running",
|
name: "valid config, is master and all components are running",
|
||||||
cfgFile: "../cfg/config.yaml",
|
cfgFile: "../cfg/config.yaml",
|
||||||
getBinariesFunc: func(viper *viper.Viper) (strings map[string]string, i error) {
|
getBinariesFunc: func(viper *viper.Viper, nt check.NodeType) (strings map[string]string, i error) {
|
||||||
return map[string]string{"apiserver": "kube-apiserver"}, nil
|
return map[string]string{"apiserver": "kube-apiserver"}, nil
|
||||||
},
|
},
|
||||||
isMaster: true,
|
isMaster: true,
|
||||||
@ -131,7 +132,7 @@ func TestIsMaster(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "valid config, is master and but not all components are running",
|
name: "valid config, is master and but not all components are running",
|
||||||
cfgFile: "../cfg/config.yaml",
|
cfgFile: "../cfg/config.yaml",
|
||||||
getBinariesFunc: func(viper *viper.Viper) (strings map[string]string, i error) {
|
getBinariesFunc: func(viper *viper.Viper, nt check.NodeType) (strings map[string]string, i error) {
|
||||||
return map[string]string{}, nil
|
return map[string]string{}, nil
|
||||||
},
|
},
|
||||||
isMaster: false,
|
isMaster: false,
|
||||||
@ -139,7 +140,7 @@ func TestIsMaster(t *testing.T) {
|
|||||||
{
|
{
|
||||||
name: "valid config, is master, not all components are running and fails to find all binaries",
|
name: "valid config, is master, not all components are running and fails to find all binaries",
|
||||||
cfgFile: "../cfg/config.yaml",
|
cfgFile: "../cfg/config.yaml",
|
||||||
getBinariesFunc: func(viper *viper.Viper) (strings map[string]string, i error) {
|
getBinariesFunc: func(viper *viper.Viper, nt check.NodeType) (strings map[string]string, i error) {
|
||||||
return map[string]string{}, errors.New("failed to find binaries")
|
return map[string]string{}, errors.New("failed to find binaries")
|
||||||
},
|
},
|
||||||
isMaster: false,
|
isMaster: false,
|
||||||
|
56
cmd/util.go
56
cmd/util.go
@ -27,7 +27,7 @@ var (
|
|||||||
|
|
||||||
var psFunc func(string) string
|
var psFunc func(string) string
|
||||||
var statFunc func(string) (os.FileInfo, error)
|
var statFunc func(string) (os.FileInfo, error)
|
||||||
var getBinariesFunc func(*viper.Viper) (map[string]string, error)
|
var getBinariesFunc func(*viper.Viper, check.NodeType) (map[string]string, error)
|
||||||
var TypeMap = map[string][]string{
|
var TypeMap = map[string][]string{
|
||||||
"ca": []string{"cafile", "defaultcafile"},
|
"ca": []string{"cafile", "defaultcafile"},
|
||||||
"kubeconfig": []string{"kubeconfig", "defaultkubeconfig"},
|
"kubeconfig": []string{"kubeconfig", "defaultkubeconfig"},
|
||||||
@ -89,7 +89,7 @@ func ps(proc string) string {
|
|||||||
|
|
||||||
// getBinaries finds which of the set of candidate executables are running.
|
// getBinaries finds which of the set of candidate executables are running.
|
||||||
// It returns an error if one mandatory executable is not running.
|
// It returns an error if one mandatory executable is not running.
|
||||||
func getBinaries(v *viper.Viper) (map[string]string, error) {
|
func getBinaries(v *viper.Viper, nodetype check.NodeType) (map[string]string, error) {
|
||||||
binmap := make(map[string]string)
|
binmap := make(map[string]string)
|
||||||
|
|
||||||
for _, component := range v.GetStringSlice("components") {
|
for _, component := range v.GetStringSlice("components") {
|
||||||
@ -103,7 +103,8 @@ func getBinaries(v *viper.Viper) (map[string]string, error) {
|
|||||||
if len(bins) > 0 {
|
if len(bins) > 0 {
|
||||||
bin, err := findExecutable(bins)
|
bin, err := findExecutable(bins)
|
||||||
if err != nil && !optional {
|
if err != nil && !optional {
|
||||||
return nil, fmt.Errorf("need %s executable but none of the candidates are running", component)
|
glog.Warning(buildComponentMissingErrorMessage(nodetype, component, bins))
|
||||||
|
return nil, fmt.Errorf("unable to detect running programs for component %q", component)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default the executable name that we'll substitute to the name of the component
|
// Default the executable name that we'll substitute to the name of the component
|
||||||
@ -269,6 +270,25 @@ func multiWordReplace(s string, subname string, sub string) string {
|
|||||||
return strings.Replace(s, subname, sub, -1)
|
return strings.Replace(s, subname, sub, -1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const missingKubectlKubeletMessage = `
|
||||||
|
Unable to find the programs kubectl or kubelet in the PATH.
|
||||||
|
These programs are used to determine which version of Kubernetes is running.
|
||||||
|
Make sure the /usr/bin directory is mapped to the container,
|
||||||
|
either in the job.yaml file, or Docker command.
|
||||||
|
|
||||||
|
For job.yaml:
|
||||||
|
...
|
||||||
|
- name: usr-bin
|
||||||
|
mountPath: /usr/bin
|
||||||
|
...
|
||||||
|
|
||||||
|
For docker command:
|
||||||
|
docker -v $(which kubectl):/usr/bin/kubectl ....
|
||||||
|
|
||||||
|
Alternatively, you can specify the version with --version
|
||||||
|
kube-bench --version <VERSION> ...
|
||||||
|
`
|
||||||
|
|
||||||
func getKubeVersion() (string, error) {
|
func getKubeVersion() (string, error) {
|
||||||
// These executables might not be on the user's path.
|
// These executables might not be on the user's path.
|
||||||
_, err := exec.LookPath("kubectl")
|
_, err := exec.LookPath("kubectl")
|
||||||
@ -282,7 +302,9 @@ func getKubeVersion() (string, error) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
return getVersionFromKubeletOutput(string(out)), nil
|
return getVersionFromKubeletOutput(string(out)), nil
|
||||||
}
|
}
|
||||||
return "", fmt.Errorf("need kubectl or kubelet binaries to get kubernetes version")
|
|
||||||
|
glog.Warning(missingKubectlKubeletMessage)
|
||||||
|
return "", fmt.Errorf("unable to find the programs kubectl or kubelet in the PATH")
|
||||||
}
|
}
|
||||||
return getKubeVersionFromKubelet(), nil
|
return getKubeVersionFromKubelet(), nil
|
||||||
}
|
}
|
||||||
@ -344,3 +366,29 @@ func makeSubstitutions(s string, ext string, m map[string]string) string {
|
|||||||
|
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildComponentMissingErrorMessage(nodetype check.NodeType, component string, bins []string) string {
|
||||||
|
|
||||||
|
errMessageTemplate := `
|
||||||
|
Unable to detect running programs for component %q
|
||||||
|
The following %q programs have been searched, but none of them have been found:
|
||||||
|
%s
|
||||||
|
|
||||||
|
These program names are provided in the config.yaml, section '%s.%s.bins'
|
||||||
|
`
|
||||||
|
|
||||||
|
componentRoleName := "master node"
|
||||||
|
componentType := "master"
|
||||||
|
|
||||||
|
if nodetype == check.NODE {
|
||||||
|
componentRoleName = "worker node"
|
||||||
|
componentType = "node"
|
||||||
|
}
|
||||||
|
|
||||||
|
binList := ""
|
||||||
|
for _, bin := range bins {
|
||||||
|
binList = fmt.Sprintf("%s\t- %s\n", binList, bin)
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(errMessageTemplate, component, componentRoleName, binList, componentType, component)
|
||||||
|
}
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/aquasecurity/kube-bench/check"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -166,7 +167,7 @@ func TestGetBinaries(t *testing.T) {
|
|||||||
for k, val := range c.config {
|
for k, val := range c.config {
|
||||||
v.Set(k, val)
|
v.Set(k, val)
|
||||||
}
|
}
|
||||||
m, err := getBinaries(v)
|
m, err := getBinaries(v, check.MASTER)
|
||||||
if c.expectErr {
|
if c.expectErr {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("Got nil Expected error")
|
t.Fatal("Got nil Expected error")
|
||||||
|
Loading…
Reference in New Issue
Block a user