Skip to content

Commit

Permalink
feat(cli): Install clustervulnerabilityreports CRD (#728)
Browse files Browse the repository at this point in the history
Signed-off-by: Daniel Pacak <[email protected]>
  • Loading branch information
danielpacak authored Oct 2, 2021
1 parent d65aded commit 5ef4f3a
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 26 deletions.
6 changes: 3 additions & 3 deletions docs/cli/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,10 @@ of Kubernetes workloads deployed in your cluster.
To begin with, execute the following one-time setup command:

```
starboard init
starboard install
```

The `init` subcommand creates the `starboard` namespace, in which Starboard executes Kubernetes jobs to perform
The `install` subcommand creates the `starboard` namespace, in which Starboard executes Kubernetes jobs to perform
scans. It also sends custom security resources definitions to the Kubernetes API:

```console
Expand All @@ -36,7 +36,7 @@ vulnerabilityreports vulns,vuln aquasecurity.github.io true Vulne
```

!!! tip
There's also a `starboard cleanup` subcommand, which can be used to remove all resources created by Starboard.
There's also a `starboard uninstall` subcommand, which can be used to remove all resources created by Starboard.

As an example let's run in the current namespace an old version of `nginx` that we know has vulnerabilities:

Expand Down
6 changes: 6 additions & 0 deletions embedded.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import (
var (
//go:embed deploy/crd/vulnerabilityreports.crd.yaml
vulnerabilityReportsCRD []byte
//go:embed deploy/crd/clustervulnerabilityreports.crd.yaml
clusterVulnerabilityReportsCRD []byte
//go:embed deploy/crd/configauditreports.crd.yaml
configAuditReportsCRD []byte
//go:embed deploy/crd/clusterconfigauditreports.crd.yaml
Expand All @@ -24,6 +26,10 @@ func GetVulnerabilityReportsCRD() (apiextensionsv1.CustomResourceDefinition, err
return getCRDFromBytes(vulnerabilityReportsCRD)
}

func GetClusterVulnerabilityReportsCRD() (apiextensionsv1.CustomResourceDefinition, error) {
return getCRDFromBytes(clusterVulnerabilityReportsCRD)
}

func GetConfigAuditReportsCRD() (apiextensionsv1.CustomResourceDefinition, error) {
return getCRDFromBytes(configAuditReportsCRD)
}
Expand Down
25 changes: 20 additions & 5 deletions itest/starboard/starboard_cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ var _ = Describe("Starboard CLI", func() {

BeforeEach(func() {
err := cmd.Run(versionInfo, []string{
"starboard", "init",
"starboard", "install",
"-v", starboardCLILogLevel,
}, GinkgoWriter, GinkgoWriter)
Expect(err).ToNot(HaveOccurred())
})

Describe("Command init", func() {
Describe("Command install", func() {

It("should initialize Starboard", func() {

Expand All @@ -68,6 +68,21 @@ var _ = Describe("Starboard CLI", func() {
"Scope": Equal(apiextensionsv1beta1.NamespaceScoped),
}),
}),
"clustervulnerabilityreports.aquasecurity.github.io": MatchFields(IgnoreExtras, Fields{
"Spec": MatchFields(IgnoreExtras, Fields{
"Group": Equal("aquasecurity.github.io"),
"Version": Equal("v1alpha1"),
"Names": Equal(apiextensionsv1beta1.CustomResourceDefinitionNames{
Plural: "clustervulnerabilityreports",
Singular: "clustervulnerabilityreport",
ShortNames: []string{"clustervuln", "clustervulns"},
Kind: "ClusterVulnerabilityReport",
ListKind: "ClusterVulnerabilityReportList",
Categories: []string{"all"},
}),
"Scope": Equal(apiextensionsv1beta1.ClusterScoped),
}),
}),
"configauditreports.aquasecurity.github.io": MatchFields(IgnoreExtras, Fields{
"Spec": MatchFields(IgnoreExtras, Fields{
"Group": Equal("aquasecurity.github.io"),
Expand Down Expand Up @@ -630,7 +645,7 @@ var _ = Describe("Starboard CLI", func() {
})
})

Describe("Command get vulnerabilities", func() {
Describe("Command get vulnerabilityreports", func() {
Context("for deployment/nginx resource", func() {
When("vulnerabilities are associated with the deployment itself", func() {

Expand Down Expand Up @@ -662,7 +677,7 @@ var _ = Describe("Starboard CLI", func() {
stderr := NewBuffer()

err := cmd.Run(versionInfo, []string{
"starboard", "get", "vulnerabilities",
"starboard", "get", "vulnerabilityreports",
"deployment/" + deploy.Name,
"--namespace", deploy.Namespace,
"-v", starboardCLILogLevel,
Expand Down Expand Up @@ -1107,7 +1122,7 @@ var _ = Describe("Starboard CLI", func() {
AfterEach(func() {
err := cmd.Run(versionInfo, []string{
"starboard",
"cleanup",
"uninstall",
"-v", starboardCLILogLevel,
}, GinkgoWriter, GinkgoWriter)
Expect(err).ToNot(HaveOccurred())
Expand Down
2 changes: 2 additions & 0 deletions pkg/apis/aquasecurity/v1alpha1/vulnerability_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const (
VulnerabilityReportsCRVersion = "v1alpha1"
VulnerabilityReportKind = "VulnerabilityReport"
VulnerabilityReportListKind = "VulnerabilityReportList"

ClusterVulnerabilityReportsCRName = "clustervulnerabilityreports.aquasecurity.github.io"
)

type Severity string
Expand Down
5 changes: 3 additions & 2 deletions pkg/cmd/cleanup.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ import (

func NewCleanupCmd(buildInfo starboard.BuildInfo, cf *genericclioptions.ConfigFlags) *cobra.Command {
cmd := &cobra.Command{
Use: "cleanup",
Short: "Delete Kubernetes resources created by Starboard",
Use: "uninstall",
Aliases: []string{"cleanup"},
Short: "Delete Kubernetes resources created by Starboard",
RunE: func(cmd *cobra.Command, args []string) error {
kubeConfig, err := cf.ToRESTConfig()
if err != nil {
Expand Down
11 changes: 8 additions & 3 deletions pkg/cmd/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@ import (

func NewInitCmd(buildInfo starboard.BuildInfo, cf *genericclioptions.ConfigFlags) *cobra.Command {
cmd := &cobra.Command{
Use: "init",
Short: "Create Kubernetes resources used by Starboard",
Use: "install",
Aliases: []string{"init"},
Short: "Create Kubernetes resources used by Starboard",
Long: `Create all the resources used by Starboard. It will create the following in your
Kubernetes cluster:
- CustomResourceDefinition objects:
- "vulnerabilityreports.aquasecurity.github.io"
- "clustervulnerabilityreports.aquasecurity.github.io"
- "configauditreports.aquasecurity.github.io"
- "clusterconfigauditreports.aquasecurity.github.io"
- "ciskubebenchreports.aquasecurity.github.io"
- "kubehunterreports.aquasecurity.github.io"
- RBAC objects:
Expand All @@ -30,13 +33,15 @@ Kubernetes cluster:
- The "starboard" service account
- The "starboard" ConfigMap
- The "starboard" secret
- The "starboard-trivy-config" ConfigMap
- The "starboard-polaris-config" ConfigMap
The "starboard" ConfigMap and the "starboard" secret contain the default
config parameters. However this can be modified to change the behaviour
of the scanners.
All resources created by this command can be removed from the cluster using
the "cleanup" command.`,
the "uninstall" command.`,
RunE: func(cmd *cobra.Command, args []string) error {
kubeConfig, err := cf.ToRESTConfig()
if err != nil {
Expand Down
21 changes: 16 additions & 5 deletions pkg/cmd/installer.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,15 @@ var (
ObjectMeta: metav1.ObjectMeta{
Name: starboard.NamespaceName,
Labels: labels.Set{
"app.kubernetes.io/managed-by": "starboard",
starboard.LabelK8SAppManagedBy: "starboard",
},
},
}
serviceAccount = &corev1.ServiceAccount{
ObjectMeta: metav1.ObjectMeta{
Name: starboard.ServiceAccountName,
Labels: labels.Set{
"app.kubernetes.io/managed-by": "starboard",
starboard.LabelK8SAppManagedBy: "starboard",
},
},
AutomountServiceAccountToken: pointer.BoolPtr(false),
Expand All @@ -49,7 +49,7 @@ var (
ObjectMeta: metav1.ObjectMeta{
Name: clusterRoleStarboard,
Labels: labels.Set{
"app.kubernetes.io/managed-by": "starboard",
starboard.LabelK8SAppManagedBy: "starboard",
},
},
Rules: []rbacv1.PolicyRule{
Expand Down Expand Up @@ -102,7 +102,7 @@ var (
ObjectMeta: metav1.ObjectMeta{
Name: clusterRoleBindingStarboard,
Labels: labels.Set{
"app.kubernetes.io/managed-by": "starboard",
starboard.LabelK8SAppManagedBy: "starboard",
},
},
RoleRef: rbacv1.RoleRef{
Expand Down Expand Up @@ -155,7 +155,14 @@ func (m *Installer) Install(ctx context.Context) error {
if err != nil {
return err
}

clusterVulnerabilityReportsCRD, err := embedded.GetClusterVulnerabilityReportsCRD()
if err != nil {
return err
}
err = m.createOrUpdateCRD(ctx, &clusterVulnerabilityReportsCRD)
if err != nil {
return err
}
kubeBenchReportsCRD, err := embedded.GetCISKubeBenchReportsCRD()
if err != nil {
return err
Expand Down Expand Up @@ -395,6 +402,10 @@ func (m *Installer) Uninstall(ctx context.Context) error {
if err != nil {
return err
}
err = m.deleteCRD(ctx, v1alpha1.ClusterVulnerabilityReportsCRName)
if err != nil {
return err
}
err = m.deleteCRD(ctx, v1alpha1.CISKubeBenchReportCRName)
if err != nil {
return err
Expand Down
14 changes: 7 additions & 7 deletions pkg/cmd/get_report.go → pkg/cmd/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
)

func NewGetReportCmd(info starboard.BuildInfo, cf *genericclioptions.ConfigFlags, outWriter io.Writer) *cobra.Command {
func NewReportCmd(info starboard.BuildInfo, cf *genericclioptions.ConfigFlags, out io.Writer) *cobra.Command {
return &cobra.Command{
Use: "report (NAME | TYPE/NAME)",
Short: "Generate an HTML security report for a specified Kubernetes object",
Expand All @@ -40,13 +40,13 @@ TYPE is a Kubernetes workload. Shortcuts and API groups will be resolved, e.g. '
NAME is the name of a particular Kubernetes workload.
`, info.Executable),
Example: fmt.Sprintf(` # Generate an HTML report for a deployment with the specified name and save it to a file.
%[1]s get report deployment/nginx > nginx.deploy.html
%[1]s report deployment/nginx > nginx.deploy.html
# Generate an HTML report for a namespace with the specified name and save it to a file.
%[1]s get report namespace/kube-system > kube-system.ns.html
%[1]s report namespace/kube-system > kube-system.ns.html
# Generate an HTML report for a node with the specified name and save it to a file.
%[1]s get report node/kind-control-plane > kind-control-plane.node.html
%[1]s report node/kind-control-plane > kind-control-plane.node.html
`, info.Executable),
RunE: func(cmd *cobra.Command, args []string) error {
kubeConfig, err := cf.ToRESTConfig()
Expand Down Expand Up @@ -77,13 +77,13 @@ NAME is the name of a particular Kubernetes workload.
kube.KindJob,
kube.KindPod:
reporter := report.NewWorkloadReporter(clock, kubeClient)
return reporter.Generate(workload, outWriter)
return reporter.Generate(workload, out)
case kube.KindNamespace:
reporter := report.NewNamespaceReporter(clock, kubeClient)
return reporter.Generate(workload, outWriter)
return reporter.Generate(workload, out)
case kube.KindNode:
reporter := report.NewNodeReporter(clock, kubeClient)
return reporter.Generate(workload, outWriter)
return reporter.Generate(workload, out)
default:
return fmt.Errorf("HTML report is not supported for %q", workload.Kind)
}
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func NewRootCmd(buildInfo starboard.BuildInfo, args []string, outWriter io.Write
rootCmd.AddCommand(NewInitCmd(buildInfo, cf))
rootCmd.AddCommand(NewScanCmd(buildInfo, cf))
rootCmd.AddCommand(NewGetCmd(buildInfo, cf, outWriter))
rootCmd.AddCommand(NewGetReportCmd(buildInfo, cf, outWriter))
rootCmd.AddCommand(NewReportCmd(buildInfo, cf, outWriter))
rootCmd.AddCommand(NewCleanupCmd(buildInfo, cf))
rootCmd.AddCommand(NewConfigCmd(cf, outWriter))

Expand Down

0 comments on commit 5ef4f3a

Please sign in to comment.