From d79a2a54783208a9021a9ea81d55cffe92d7e7c8 Mon Sep 17 00:00:00 2001 From: Steven Logue Date: Tue, 31 Oct 2017 13:08:46 -0700 Subject: [PATCH 1/3] added support for saving scan results to pgsql --- check/controls.go | 8 +++--- cmd/common.go | 65 ++++++++++++++++++++++++++++++++++++++++++++++- cmd/root.go | 10 +++++--- makefile | 2 +- 4 files changed, 75 insertions(+), 10 deletions(-) diff --git a/check/controls.go b/check/controls.go index 909adb7..8660e81 100644 --- a/check/controls.go +++ b/check/controls.go @@ -23,11 +23,11 @@ import ( // Controls holds all controls to check for master nodes. type Controls struct { - ID string `yaml:"id"` + ID string `yaml:"id"` Version string - Text string - Type NodeType - Groups []*Group + Text string + Type NodeType + Groups []*Group Summary } diff --git a/cmd/common.go b/cmd/common.go index b618cff..28fe8ba 100644 --- a/cmd/common.go +++ b/cmd/common.go @@ -18,8 +18,13 @@ import ( "fmt" "io/ioutil" + "os" + "time" + "github.com/aquasecurity/kube-bench/check" "github.com/golang/glog" + "github.com/jinzhu/gorm" + _ "github.com/jinzhu/gorm/dialects/postgres" "github.com/spf13/viper" ) @@ -118,7 +123,17 @@ func runChecks(t check.NodeType) { fmt.Println(string(out)) } else { - prettyPrint(controls, summary) + // 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) + } } } @@ -168,3 +183,51 @@ func prettyPrint(r *check.Controls, summary check.Summary) { summary.Pass, summary.Fail, summary.Warn, ) } + +func savePgsql(jsonInfo string) { + envVars := map[string]string{ + "PGSQL_HOST": viper.GetString("PGSQL_HOST"), + "PGSQL_USER": viper.GetString("PGSQL_USER"), + "PGSQL_DBNAME": viper.GetString("PGSQL_DBNAME"), + "PGSQL_SSLMODE": viper.GetString("PGSQL_SSLMODE"), + "PGSQL_PASSWORD": viper.GetString("PGSQL_PASSWORD"), + } + + for k, v := range envVars { + if v == "" { + err := fmt.Errorf("Environment variable %s missing", envVarsPrefix+"_"+k) + panic(err) + } + } + + connInfo := fmt.Sprintf("host=%s user=%s dbname=%s sslmode=%s password=%s", + envVars["PGSQL_HOST"], + envVars["PGSQL_USER"], + envVars["PGSQL_DBNAME"], + envVars["PGSQL_SSLMODE"], + envVars["PGSQL_PASSWORD"], + ) + + hostname, err := os.Hostname() + if err != nil { + panic(err) + } + + timestamp := time.Now() + + type ScanResult struct { + gorm.Model + ScanHost string `gorm:"type:varchar(63) not null"` // https://www.ietf.org/rfc/rfc1035.txt + ScanTime time.Time `gorm:"not null"` + ScanInfo string `gorm:"type:jsonb not null"` + } + + db, err := gorm.Open("postgres", connInfo) + defer db.Close() + if err != nil { + panic(err) + } + + db.Debug().AutoMigrate(&ScanResult{}) + db.Save(&ScanResult{ScanHost: hostname, ScanTime: timestamp, ScanInfo: jsonInfo}) +} diff --git a/cmd/root.go b/cmd/root.go index 601804e..08be2b3 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -25,10 +25,11 @@ import ( ) var ( - cfgDir = "./cfg" - cfgFile string - + envVarsPrefix = "KUBE_BENCH" + cfgDir = "./cfg" + cfgFile string jsonFmt bool + pgSql bool checkList string groupList string masterFile string @@ -59,6 +60,7 @@ func init() { cobra.OnInitialize(initConfig) RootCmd.PersistentFlags().BoolVar(&jsonFmt, "json", false, "Prints the results as JSON") + RootCmd.PersistentFlags().BoolVar(&pgSql, "pgsql", false, "Save the results to PostgreSQL") RootCmd.PersistentFlags().StringVarP( &checkList, "check", @@ -90,7 +92,7 @@ func initConfig() { viper.AddConfigPath(cfgDir) // adding ./cfg as first search path } - viper.SetEnvPrefix("KUBE_BENCH") + viper.SetEnvPrefix(envVarsPrefix) viper.AutomaticEnv() // read in environment variables that match // If a config file is found, read it in. diff --git a/makefile b/makefile index c0a68dd..53cdb79 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -SOURCES := $(shell find . -name '*.go') +OURCES := $(shell find . -name '*.go') TARGET_OS := linux BINARY := kube-bench From f7d4f03f48249cb30d1b4231213fe5053cd96550 Mon Sep 17 00:00:00 2001 From: Steven Logue Date: Tue, 31 Oct 2017 13:12:20 -0700 Subject: [PATCH 2/3] fixed typo in makefile --- makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/makefile b/makefile index 53cdb79..c0a68dd 100644 --- a/makefile +++ b/makefile @@ -1,4 +1,4 @@ -OURCES := $(shell find . -name '*.go') +SOURCES := $(shell find . -name '*.go') TARGET_OS := linux BINARY := kube-bench From 909e6cc8745dcc33ff67b248cea39d0f8fce686f Mon Sep 17 00:00:00 2001 From: Steven Logue Date: Wed, 1 Nov 2017 10:15:31 -0700 Subject: [PATCH 3/3] created database.go file and moved DB function into it --- cmd/common.go | 53 ------------------------------------------- cmd/database.go | 60 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 53 deletions(-) create mode 100644 cmd/database.go diff --git a/cmd/common.go b/cmd/common.go index e65466b..3e01f2a 100644 --- a/cmd/common.go +++ b/cmd/common.go @@ -18,13 +18,8 @@ import ( "fmt" "io/ioutil" - "os" - "time" - "github.com/aquasecurity/kube-bench/check" "github.com/golang/glog" - "github.com/jinzhu/gorm" - _ "github.com/jinzhu/gorm/dialects/postgres" "github.com/spf13/viper" ) @@ -169,51 +164,3 @@ func prettyPrint(r *check.Controls, summary check.Summary) { summary.Pass, summary.Fail, summary.Warn, ) } - -func savePgsql(jsonInfo string) { - envVars := map[string]string{ - "PGSQL_HOST": viper.GetString("PGSQL_HOST"), - "PGSQL_USER": viper.GetString("PGSQL_USER"), - "PGSQL_DBNAME": viper.GetString("PGSQL_DBNAME"), - "PGSQL_SSLMODE": viper.GetString("PGSQL_SSLMODE"), - "PGSQL_PASSWORD": viper.GetString("PGSQL_PASSWORD"), - } - - for k, v := range envVars { - if v == "" { - err := fmt.Errorf("Environment variable %s missing", envVarsPrefix+"_"+k) - panic(err) - } - } - - connInfo := fmt.Sprintf("host=%s user=%s dbname=%s sslmode=%s password=%s", - envVars["PGSQL_HOST"], - envVars["PGSQL_USER"], - envVars["PGSQL_DBNAME"], - envVars["PGSQL_SSLMODE"], - envVars["PGSQL_PASSWORD"], - ) - - hostname, err := os.Hostname() - if err != nil { - panic(err) - } - - timestamp := time.Now() - - type ScanResult struct { - gorm.Model - ScanHost string `gorm:"type:varchar(63) not null"` // https://www.ietf.org/rfc/rfc1035.txt - ScanTime time.Time `gorm:"not null"` - ScanInfo string `gorm:"type:jsonb not null"` - } - - db, err := gorm.Open("postgres", connInfo) - defer db.Close() - if err != nil { - panic(err) - } - - db.Debug().AutoMigrate(&ScanResult{}) - db.Save(&ScanResult{ScanHost: hostname, ScanTime: timestamp, ScanInfo: jsonInfo}) -} diff --git a/cmd/database.go b/cmd/database.go new file mode 100644 index 0000000..46668ae --- /dev/null +++ b/cmd/database.go @@ -0,0 +1,60 @@ +package cmd + +import ( + "fmt" + "os" + "time" + + "github.com/golang/glog" + "github.com/jinzhu/gorm" + _ "github.com/jinzhu/gorm/dialects/postgres" + "github.com/spf13/viper" +) + +func savePgsql(jsonInfo string) { + envVars := map[string]string{ + "PGSQL_HOST": viper.GetString("PGSQL_HOST"), + "PGSQL_USER": viper.GetString("PGSQL_USER"), + "PGSQL_DBNAME": viper.GetString("PGSQL_DBNAME"), + "PGSQL_SSLMODE": viper.GetString("PGSQL_SSLMODE"), + "PGSQL_PASSWORD": viper.GetString("PGSQL_PASSWORD"), + } + + for k, v := range envVars { + if v == "" { + exitWithError(fmt.Errorf("environment variable %s is missing", envVarsPrefix+"_"+k)) + } + } + + connInfo := fmt.Sprintf("host=%s user=%s dbname=%s sslmode=%s password=%s", + envVars["PGSQL_HOST"], + envVars["PGSQL_USER"], + envVars["PGSQL_DBNAME"], + envVars["PGSQL_SSLMODE"], + envVars["PGSQL_PASSWORD"], + ) + + hostname, err := os.Hostname() + if err != nil { + exitWithError(fmt.Errorf("received error looking up hostname: %s", err)) + } + + timestamp := time.Now() + + type ScanResult struct { + gorm.Model + ScanHost string `gorm:"type:varchar(63) not null"` // https://www.ietf.org/rfc/rfc1035.txt + ScanTime time.Time `gorm:"not null"` + ScanInfo string `gorm:"type:jsonb not null"` + } + + db, err := gorm.Open("postgres", connInfo) + defer db.Close() + if err != nil { + exitWithError(fmt.Errorf("received error connecting to database: %s", err)) + } + + db.Debug().AutoMigrate(&ScanResult{}) + db.Save(&ScanResult{ScanHost: hostname, ScanTime: timestamp, ScanInfo: jsonInfo}) + glog.V(2).Info(fmt.Sprintf("successfully stored result to: %s", envVars["PGSQL_HOST"])) +}