From d453e521f630e43afc9e7dc66c0eb7b11d0e89a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Cuadrado=20Juan?= Date: Fri, 1 Sep 2023 17:48:47 +0200 Subject: [PATCH] refactor: Rename `--print` flag to `--log-fmt`, accepts `json` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: VĂ­ctor Cuadrado Juan --- CONTRIBUTING.md | 6 +- cmd/root.go | 110 ++++++++++++++++++++---------------- internal/scanner/scanner.go | 13 +++-- 3 files changed, 71 insertions(+), 58 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e87da912..6651ed16 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -20,7 +20,7 @@ or to get results in JSON: ./bin/audit-scanner \ -k kubewarden --namespace default \ --policy-server-url https://localhost:3000 \ - -l debug --print + -l debug --log-fmt=json ``` ### Run against audit-scanner SA @@ -38,8 +38,8 @@ If needed, patch the resulting kubeconfig, adding the missing ```yaml clusters: -- cluster: - certificate-authority: /home/vic/.minikube/ca.crt + - cluster: + certificate-authority: /home/vic/.minikube/ca.crt ``` And use it: diff --git a/cmd/root.go b/cmd/root.go index a94b7c1a..6b648628 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -26,8 +26,11 @@ type Scanner interface { // log level var level logconfig.Level -// print result of scan as JSON to stdout -var printJSON bool +// format of logs to stdout & stderr +var logFormat string + +// list of supported format of logs to stdout & stderr +var logFormatSupportedFormats = [1]string{"json"} // list of namespaces to be skipped from scan var skippedNs []string @@ -35,55 +38,63 @@ var skippedNs []string // skip SSL cert validation when connecting to PolicyServers endpoints var insecureSSL bool -var ( - // rootCmd represents the base command when called without any subcommands - rootCmd = &cobra.Command{ - Use: "audit-scanner", - Short: "Reports evaluation of existing Kubernetes resources with your already deployed Kubewarden policies", - Long: `Scans resources in your kubernetes cluster with your already deployed Kubewarden policies. +// rootCmd represents the base command when called without any subcommands +var rootCmd = &cobra.Command{ + Use: "audit-scanner", + Short: "Reports evaluation of existing Kubernetes resources with your already deployed Kubewarden policies", + Long: `Scans resources in your kubernetes cluster with your already deployed Kubewarden policies. Each namespace will have a PolicyReport with the outcome of the scan for resources within this namespace. There will be a ClusterPolicyReport with results for cluster-wide resources.`, - RunE: func(cmd *cobra.Command, args []string) error { - level.SetZeroLogLevel() - namespace, err := cmd.Flags().GetString("namespace") - if err != nil { - return err - } - kubewardenNamespace, err := cmd.Flags().GetString("kubewarden-namespace") - if err != nil { - return err - } - clusterWide, err := cmd.Flags().GetBool("cluster") - if err != nil { - return err - } - policyServerURL, err := cmd.Flags().GetString("policy-server-url") - if err != nil { - return err - } - caCertFile, err := cmd.Flags().GetString("extra-ca") - if err != nil { - return err - } - - policiesFetcher, err := policies.NewFetcher(kubewardenNamespace, skippedNs) - if err != nil { - return err - } - resourcesFetcher, err := resources.NewFetcher(kubewardenNamespace, policyServerURL) - if err != nil { - return err - } - scanner, err := scanner.NewScanner(policiesFetcher, resourcesFetcher, printJSON, insecureSSL, caCertFile) - if err != nil { - return err - } - - return startScanner(namespace, clusterWide, scanner) - }, - } -) + RunE: func(cmd *cobra.Command, args []string) error { + level.SetZeroLogLevel() + namespace, err := cmd.Flags().GetString("namespace") + if err != nil { + return err + } + kubewardenNamespace, err := cmd.Flags().GetString("kubewarden-namespace") + if err != nil { + return err + } + clusterWide, err := cmd.Flags().GetBool("cluster") + if err != nil { + return err + } + policyServerURL, err := cmd.Flags().GetString("policy-server-url") + if err != nil { + return err + } + caCertFile, err := cmd.Flags().GetString("extra-ca") + if err != nil { + return err + } + logFormat, err := cmd.Flags().GetString("log-fmt") + if err != nil { + return err + } + switch logFormat { + // TODO use slices package in go 1.21 + case "json": // skip + default: + return fmt.Errorf("passed log-fmt not supported. Please select one of the supported formats: %v", logFormatSupportedFormats) + } + + policiesFetcher, err := policies.NewFetcher(kubewardenNamespace, skippedNs) + if err != nil { + return err + } + resourcesFetcher, err := resources.NewFetcher(kubewardenNamespace, policyServerURL) + if err != nil { + return err + } + scanner, err := scanner.NewScanner(policiesFetcher, resourcesFetcher, logFormat, insecureSSL, caCertFile) + if err != nil { + return err + } + + return startScanner(namespace, clusterWide, scanner) + }, +} // Execute adds all child commands to the root command and sets flags appropriately. // This is called by main.main(). It only needs to happen once to the rootCmd. @@ -96,6 +107,7 @@ func Execute() { log.Fatal().Err(err).Msg("Error on cmd.Execute()") } } + func startScanner(namespace string, clusterWide bool, scanner Scanner) error { if clusterWide && namespace != "" { log.Fatal().Msg("Cannot scan cluster wide and only a namespace at the same time") @@ -124,7 +136,7 @@ func init() { rootCmd.Flags().StringP("kubewarden-namespace", "k", defaultKubewardenNamespace, "namespace where the Kubewarden components (e.g. PolicyServer) are installed (required)") rootCmd.Flags().StringP("policy-server-url", "u", "", "URI to the PolicyServers the Audit Scanner will query. Example: https://localhost:3000. Useful for out-of-cluster debugging") rootCmd.Flags().VarP(&level, "loglevel", "l", fmt.Sprintf("level of the logs. Supported values are: %v", logconfig.SupportedValues)) - rootCmd.Flags().BoolVarP(&printJSON, "print", "p", false, "print result of scan in JSON to stdout") + rootCmd.Flags().StringP("log-fmt", "o", logFormat, fmt.Sprintf("If set, print output result of scan to stdout in speficied format. Supported formats: %v", logFormatSupportedFormats)) rootCmd.Flags().StringSliceVarP(&skippedNs, "ignore-namespaces", "i", nil, "comma separated list of namespace names to be skipped from scan. This flag can be repeated") rootCmd.Flags().BoolVar(&insecureSSL, "insecure-ssl", false, "skip SSL cert validation when connecting to PolicyServers endpoints. Useful for development") rootCmd.Flags().StringP("extra-ca", "f", "", "File path to CA cert in PEM format of PolicyServer endpoints") diff --git a/internal/scanner/scanner.go b/internal/scanner/scanner.go index 4c6824f8..10f7d9eb 100644 --- a/internal/scanner/scanner.go +++ b/internal/scanner/scanner.go @@ -51,7 +51,7 @@ type Scanner struct { reportStore report.PolicyReportStore // http client used to make requests against the Policy Server httpClient http.Client - printJSON bool + logFormat string } // NewScanner creates a new scanner with the PoliciesFetcher provided. If @@ -59,8 +59,9 @@ type Scanner struct { // cert trust store. This gets used by the httpCLient when connection to // PolicyServers endpoints. func NewScanner(policiesFetcher PoliciesFetcher, resourcesFetcher ResourcesFetcher, - printJSON bool, - insecureClient bool, caCertFile string) (*Scanner, error) { + logFormat string, + insecureClient bool, caCertFile string, +) (*Scanner, error) { report, err := report.NewPolicyReportStore() if err != nil { return nil, err @@ -103,7 +104,7 @@ func NewScanner(policiesFetcher PoliciesFetcher, resourcesFetcher ResourcesFetch log.Warn().Msg("connecting to PolicyServers endpoints without validating TLS connection") } - return &Scanner{policiesFetcher, resourcesFetcher, *report, httpClient, printJSON}, nil + return &Scanner{policiesFetcher, resourcesFetcher, *report, httpClient, logFormat}, nil } // ScanNamespace scans resources for a given namespace. @@ -158,7 +159,7 @@ func (s *Scanner) ScanNamespace(nsName string) error { } log.Info().Str("namespace", nsName).Msg("namespace scan finished") - if s.printJSON { + if s.logFormat == "json" { str, err := s.reportStore.ToJSON() if err != nil { log.Error().Err(err).Msg("error marshaling reportStore to JSON") @@ -227,7 +228,7 @@ func (s *Scanner) ScanClusterWideResources() error { if err != nil { log.Error().Err(err).Msg("error adding PolicyReport to store") } - if s.printJSON { + if s.logFormat == "json" { str, err := s.reportStore.ToJSON() if err != nil { log.Error().Err(err).Msg("error marshaling reportStore to JSON")