Skip to content

Commit

Permalink
feat: Add subcommand to fetch vulnerability reports (#28)
Browse files Browse the repository at this point in the history
Resolves: #22

Signed-off-by: Daniel Pacak <pacak.daniel@gmail.com>
  • Loading branch information
danielpacak authored May 25, 2020
1 parent 8dd2c97 commit 8d2b8f0
Show file tree
Hide file tree
Showing 13 changed files with 187 additions and 16 deletions.
11 changes: 10 additions & 1 deletion cmd/starboard/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,21 @@ import (
"k8s.io/klog"
)

var (
// These variables are populated by GoReleases via ldflags
version = "dev"
commit = "none"
date = "unknown"
)

func main() {
defer klog.Flush()

initFlags()

if err := cmd.GetRootCmd().Execute(); err != nil {
version := cmd.VersionInfo{Version: version, Commit: commit, Date: date}

if err := cmd.NewRootCmd(version).Execute(); err != nil {
fmt.Printf("error: %v\n", err)
os.Exit(1)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/cleanup.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"k8s.io/client-go/kubernetes"
)

func GetCleanupCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
func NewCleanupCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
cmd := &cobra.Command{
Use: "cleanup",
Short: "Delete custom resource definitions created by starboard",
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/find.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"k8s.io/cli-runtime/pkg/genericclioptions"
)

func GetFindCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
func NewFindCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
findCmd := &cobra.Command{
Use: "find",
Short: "Manage security scanners",
Expand Down
18 changes: 18 additions & 0 deletions pkg/cmd/get.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package cmd

import (
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
)

func NewGetCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
getCmd := &cobra.Command{
Use: "get",
Short: "Get security reports",
}
getCmd.AddCommand(NewGetVulnerabilitiesCmd(cf))
getCmd.AddCommand(NewGetConfigAuditCmd(cf))
getCmd.PersistentFlags().StringP("output", "o", "yaml", "Output format. One of yaml|json")

return getCmd
}
58 changes: 58 additions & 0 deletions pkg/cmd/get_configaudit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package cmd

import (
"fmt"
"os/exec"

starboard "github.com/aquasecurity/starboard/pkg/apis/aquasecurity/v1alpha1"
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
)

func NewGetConfigAuditCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
cmd := &cobra.Command{
Use: "configaudit (NAME | TYPE/NAME)",
Short: "Get configuration audit report",
Long: `Get configuration audit report for the specified workload
TYPE is a Kubernetes workload. Shortcuts and API groups will be resolved, e.g. 'po' or 'deployments.apps'.
NAME is the name of a particular Kubernetes workload.
`,
Example: fmt.Sprintf(` # Get configuration audit for a Deployment with the specified name
%[1]s get configauditreports.aquasecurity.github.io deploy/nginx
# Get configuration audit for a Deployment with the specified name in the specified namespace
%[1]s get configauditreports deploy/nginx -n staging
# Get configuration audit for a ReplicaSet with the specified name
%[1]s get configaudit replicaset/nginx
# Get vulnerabilities for a CronJob with the specified name in JSON output format
%[1]s get configaudit cj/my-job -o json`, "starboard"),
RunE: func(cmd *cobra.Command, args []string) (err error) {
ns, _, err := cf.ToRawKubeConfigLoader().Namespace()
if err != nil {
return
}
workload, err := WorkloadFromArgs(ns, args)
if err != nil {
return
}

kubectlCmd := exec.Command("kubectl",
"get",
starboard.ConfigAuditReportCRName,
fmt.Sprintf("-l=starboard.resource.kind=%s,starboard.resource.name=%s", workload.Kind, workload.Name),
fmt.Sprintf("--namespace=%s", workload.Namespace),
fmt.Sprintf("--output=%s", cmd.Flag("output").Value.String()))
stdoutStderr, err := kubectlCmd.CombinedOutput()
if err != nil {
return
}
fmt.Printf("%s", stdoutStderr)
return
},
}

return cmd
}
59 changes: 59 additions & 0 deletions pkg/cmd/get_vulnerabilities.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package cmd

import (
"fmt"
"os/exec"

starboard "github.com/aquasecurity/starboard/pkg/apis/aquasecurity/v1alpha1"
"github.com/spf13/cobra"
"k8s.io/cli-runtime/pkg/genericclioptions"
)

func NewGetVulnerabilitiesCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
cmd := &cobra.Command{
Aliases: []string{"vulns", "vuln"},
Use: "vulnerabilities (NAME | TYPE/NAME)",
Short: "Get vulnerabilities report",
Long: `Get vulnerabilities report for the specified workload
TYPE is a Kubernetes workload. Shortcuts and API groups will be resolved, e.g. 'po' or 'deployments.apps'.
NAME is the name of a particular Kubernetes workload.
`,
Example: fmt.Sprintf(` # Get vulnerabilities for a Deployment with the specified name
%[1]s get vulnerabilities.aquasecurity.github.io deploy/nginx
# Get vulnerabilities for a Deployment with the specified name in the specified namespace
%[1]s get vulnerabilities deploy/nginx -n staging
# Get vulnerabilities for a ReplicaSet with the specified name
%[1]s get vulns replicaset/nginx
# Get vulnerabilities for a CronJob with the specified name in JSON output format
%[1]s get vuln cj/my-job -o json`, "starboard"),
RunE: func(cmd *cobra.Command, args []string) (err error) {
ns, _, err := cf.ToRawKubeConfigLoader().Namespace()
if err != nil {
return
}
workload, err := WorkloadFromArgs(ns, args)
if err != nil {
return
}

kubectlCmd := exec.Command("kubectl",
"get",
starboard.VulnerabilitiesCRName,
fmt.Sprintf("-l=starboard.resource.kind=%s,starboard.resource.name=%s", workload.Kind, workload.Name),
fmt.Sprintf("--namespace=%s", workload.Namespace),
fmt.Sprintf("--output=%s", cmd.Flag("output").Value.String()))
stdoutStderr, err := kubectlCmd.CombinedOutput()
if err != nil {
return
}
fmt.Printf("%s", stdoutStderr)
return
},
}

return cmd
}
2 changes: 1 addition & 1 deletion pkg/cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"k8s.io/client-go/kubernetes"
)

func GetInitCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
func NewInitCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
cmd := &cobra.Command{
Use: "init",
Short: "Create custom resource definitions used by starboard",
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/kube_bench.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"k8s.io/client-go/kubernetes"
)

func GetKubeBenchCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
func NewKubeBenchCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
cmd := &cobra.Command{
Use: "kube-bench",
Short: "Run the CIS Kubernetes Benchmark https://www.cisecurity.org/benchmark/kubernetes",
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/kube_hunter.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"k8s.io/client-go/kubernetes"
)

func GetKubeHunterCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
func NewKubeHunterCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
cmd := &cobra.Command{
Use: "kube-hunter",
Short: "Hunt for security weaknesses",
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/polaris.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"k8s.io/client-go/kubernetes"
)

func GetPolarisCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
func NewPolarisCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
cmd := &cobra.Command{
Use: "polaris",
Short: "Run a variety of checks to ensure that Kubernetes pods and controllers are configured using best practices",
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/rbac.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"k8s.io/cli-runtime/pkg/genericclioptions"
)

func GetRBACCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
func NewRBACCmd(cf *genericclioptions.ConfigFlags) *cobra.Command {
cmd := &cobra.Command{
Use: "rbac",
Short: "Get RBAC config to run starboard",
Expand Down
18 changes: 10 additions & 8 deletions pkg/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
"k8s.io/cli-runtime/pkg/genericclioptions"
)

func GetRootCmd() *cobra.Command {
func NewRootCmd(version VersionInfo) *cobra.Command {
var cf *genericclioptions.ConfigFlags

rootCmd := &cobra.Command{
Expand All @@ -22,13 +22,15 @@ func GetRootCmd() *cobra.Command {

cf = genericclioptions.NewConfigFlags(true)

rootCmd.AddCommand(GetInitCmd(cf))
rootCmd.AddCommand(GetRBACCmd(cf))
rootCmd.AddCommand(GetFindCmd(cf))
rootCmd.AddCommand(GetKubeBenchCmd(cf))
rootCmd.AddCommand(GetKubeHunterCmd(cf))
rootCmd.AddCommand(GetPolarisCmd(cf))
rootCmd.AddCommand(GetCleanupCmd(cf))
rootCmd.AddCommand(NewVersionCmd(version))
rootCmd.AddCommand(NewInitCmd(cf))
rootCmd.AddCommand(NewRBACCmd(cf))
rootCmd.AddCommand(NewFindCmd(cf))
rootCmd.AddCommand(NewKubeBenchCmd(cf))
rootCmd.AddCommand(NewKubeHunterCmd(cf))
rootCmd.AddCommand(NewPolarisCmd(cf))
rootCmd.AddCommand(NewGetCmd(cf))
rootCmd.AddCommand(NewCleanupCmd(cf))

SetFlags(cf, rootCmd)

Expand Down
25 changes: 25 additions & 0 deletions pkg/cmd/version.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package cmd

import (
"fmt"

"github.com/spf13/cobra"
)

type VersionInfo struct {
Version string
Commit string
Date string
}

func NewVersionCmd(version VersionInfo) *cobra.Command {
cmd := &cobra.Command{
Use: "version",
Short: "Print the version information",
RunE: func(cmd *cobra.Command, args []string) (err error) {
fmt.Printf("Starboard Version: %+v\n", version)
return
},
}
return cmd
}

0 comments on commit 8d2b8f0

Please sign in to comment.