1
0
mirror of https://github.com/aquasecurity/kube-bench.git synced 2024-12-24 07:28:06 +00:00
kube-bench/cmd/common.go

170 lines
4.6 KiB
Go
Raw Normal View History

2017-05-26 09:25:29 +00:00
// 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"
2017-05-26 09:25:29 +00:00
"github.com/spf13/viper"
)
var (
apiserverBin string
apiserverConf string
schedulerBin string
schedulerConf string
controllerManagerBin string
controllerManagerConf string
config string
etcdBin string
etcdConf string
flanneldBin string
flanneldConf string
kubeletBin string
kubeletConf string
proxyBin string
proxyConf string
fedApiserverBin string
fedControllerManagerBin string
errmsgs string
2017-05-26 09:25:29 +00:00
)
func runChecks(t check.NodeType) {
var summary check.Summary
var file string
var err error
var typeConf *viper.Viper
2017-05-26 09:25:29 +00:00
glog.V(1).Info(fmt.Sprintf("Using config file: %s\n", viper.ConfigFileUsed()))
switch t {
case check.MASTER:
file = masterFile
typeConf = viper.Sub("master")
case check.NODE:
file = nodeFile
typeConf = viper.Sub("node")
case check.FEDERATED:
file = federatedFile
typeConf = viper.Sub("federated")
}
// 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)
2017-05-26 09:25:29 +00:00
switch t {
case check.MASTER:
file = masterFile
case check.NODE:
file = nodeFile
case check.FEDERATED:
file = federatedFile
}
ver := getKubeVersion()
path := fmt.Sprintf("%s/%s/%s", cfgDir, ver.Server, file)
in, err := ioutil.ReadFile(path)
2017-05-26 09:25:29 +00:00
if err != nil {
2017-07-25 00:34:07 +00:00
exitWithError(fmt.Errorf("error opening %s controls file: %v", t, err))
2017-05-26 09:25:29 +00:00
}
// Variable substitutions. Replace all occurrences of variables in controls files.
s := string(in)
s = makeSubstitutions(s, "bin", binmap)
s = makeSubstitutions(s, "conf", confmap)
2017-05-26 09:25:29 +00:00
controls, err := check.NewControls(t, []byte(s))
if err != nil {
2017-07-25 00:34:07 +00:00
exitWithError(fmt.Errorf("error setting up %s controls: %v", t, err))
}
2017-05-26 09:25:29 +00:00
if groupList != "" && checkList == "" {
ids := cleanIDs(groupList)
2017-07-25 00:34:07 +00:00
summary = controls.RunGroup(ids...)
2017-05-26 09:25:29 +00:00
} else if checkList != "" && groupList == "" {
ids := cleanIDs(checkList)
2017-07-25 00:34:07 +00:00
summary = controls.RunChecks(ids...)
2017-05-26 09:25:29 +00:00
} else if checkList != "" && groupList != "" {
2017-07-25 00:34:07 +00:00
exitWithError(fmt.Errorf("group option and check option can't be used together"))
2017-05-26 09:25:29 +00:00
} else {
2017-07-25 00:34:07 +00:00
summary = controls.RunGroup()
2017-05-26 09:25:29 +00:00
}
// 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 {
2017-05-26 09:25:29 +00:00
out, err := controls.JSON()
if err != nil {
2017-07-25 00:34:07 +00:00
exitWithError(fmt.Errorf("failed to output in JSON format: %v", err))
2017-05-26 09:25:29 +00:00
}
fmt.Println(string(out))
} else {
2017-07-25 00:34:07 +00:00
prettyPrint(controls, summary)
2017-05-26 09:25:29 +00:00
}
}
// 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)
}
2017-05-26 09:25:29 +00:00
// prettyPrint outputs the results to stdout in human-readable format
2017-07-25 00:34:07 +00:00
func prettyPrint(r *check.Controls, summary check.Summary) {
colorPrint(check.INFO, fmt.Sprintf("%s %s\n", r.ID, r.Text))
2017-05-26 09:25:29 +00:00
for _, g := range r.Groups {
2017-06-20 10:09:44 +00:00
colorPrint(check.INFO, fmt.Sprintf("%s %s\n", g.ID, g.Text))
2017-05-26 09:25:29 +00:00
for _, c := range g.Checks {
colorPrint(c.State, fmt.Sprintf("%s %s\n", c.ID, c.Text))
2017-05-26 09:25:29 +00:00
}
}
2017-05-26 09:25:29 +00:00
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,
)
}