Skip to content

Commit

Permalink
Merge pull request #165 from nnelas/feature/107-adds_logging_per_poli…
Browse files Browse the repository at this point in the history
…cy-report

feat: adds logging per `(Cluster)PolicyReport` result
  • Loading branch information
flavio authored Dec 21, 2023
2 parents 320afdb + 9988c42 commit be52c2d
Show file tree
Hide file tree
Showing 5 changed files with 73 additions and 80 deletions.
67 changes: 67 additions & 0 deletions internal/log/policy_report_logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package log

import (
"github.com/kubewarden/audit-scanner/internal/report"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)

type PolicyReportLogger struct {
}

// LogClusterPolicyReport will create a log line per each cluster-wide scanned resource
func (l *PolicyReportLogger) LogClusterPolicyReport(report *report.ClusterPolicyReport) {
log.Info().
Dict("dict", zerolog.Dict().
Int("pass", report.Summary.Pass).
Int("fail", report.Summary.Fail).
Int("warn", report.Summary.Warn).
Int("error", report.Summary.Error).
Int("skip", report.Summary.Skip)).
Msg("ClusterPolicyReport summary")

for _, result := range report.Results {
log.Info().
Dict("dict", zerolog.Dict().
Str("policy", result.Policy).
Str("rule", result.Rule).
Str("result", string(result.Result)).
Str("message", result.Description).
// although subjects is a list, there's only 1 element
Str("resource_api_version", result.Subjects[0].APIVersion).
Str("resource_kind", result.Subjects[0].Kind).
Str("resource_namespace", result.Subjects[0].Namespace).
Str("resource_name", result.Subjects[0].Name).
Str("resource_version", result.Subjects[0].ResourceVersion)).
Send()
}
}

// LogPolicyReport will create a log line per each namespace scanned resource.
func (l *PolicyReportLogger) LogPolicyReport(report *report.PolicyReport) {
log.Info().
Dict("dict", zerolog.Dict().
Str("name", report.GetName()).
Int("pass", report.Summary.Pass).
Int("fail", report.Summary.Fail).
Int("warn", report.Summary.Warn).
Int("error", report.Summary.Error).
Int("skip", report.Summary.Skip)).
Msg("PolicyReport summary")

for _, result := range report.Results {
log.Info().
Dict("dict", zerolog.Dict().
Str("policy", result.Policy).
Str("rule", result.Rule).
Str("result", string(result.Result)).
Str("message", result.Description).
// although subjects is a list, there's only 1 element
Str("resource_api_version", result.Subjects[0].APIVersion).
Str("resource_kind", result.Subjects[0].Kind).
Str("resource_namespace", result.Subjects[0].Namespace).
Str("resource_name", result.Subjects[0].Name).
Str("resource_version", result.Subjects[0].ResourceVersion)).
Send()
}
}
3 changes: 0 additions & 3 deletions internal/report/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,4 @@ type PolicyReportStore interface {
// SaveClusterPolicyReport instantiates the ClusterPolicyReport if it doesn't exist, or
// updates it one is found
SaveClusterPolicyReport(report *ClusterPolicyReport) error

// ToJSON marshals the contents of the store into a JSON string
ToJSON() (string, error)
}
40 changes: 0 additions & 40 deletions internal/report/store_kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package report

import (
"context"
"encoding/json"
"errors"
"fmt"
"strings"
Expand All @@ -13,7 +12,6 @@ import (
errorMachinery "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/util/retry"
Expand Down Expand Up @@ -208,41 +206,3 @@ func (s *KubernetesPolicyReportStore) SaveClusterPolicyReport(report *ClusterPol
}
return nil
}

func (s *KubernetesPolicyReportStore) listPolicyReports() ([]PolicyReport, error) {
reportList := polReport.PolicyReportList{}
err := s.client.List(context.Background(), &reportList, &client.ListOptions{
LabelSelector: labels.SelectorFromSet(labels.Set{LabelAppManagedBy: LabelApp}),
})
if err != nil {
if errorMachinery.IsNotFound(err) {
return []PolicyReport{}, constants.ErrResourceNotFound
}
return []PolicyReport{}, err
}
results := make([]PolicyReport, 0, len(reportList.Items))
for _, item := range reportList.Items {
results = append(results, PolicyReport{item})
}
return results, nil
}

func (s *KubernetesPolicyReportStore) ToJSON() (string, error) {
recapJSON := make(map[string]interface{})
clusterReport, err := s.GetClusterPolicyReport(constants.DefaultClusterwideReportName)
if err != nil {
log.Error().Err(err).Msg("error fetching ClusterPolicyReport. Ignoring this error to allow user to read the namespaced reports")
}
recapJSON["cluster"] = clusterReport
nsReports, err := s.listPolicyReports()
if err != nil {
return "", err
}
recapJSON["namespaces"] = nsReports

marshaled, err := json.Marshal(recapJSON)
if err != nil {
return "", err
}
return string(marshaled), nil
}
27 changes: 0 additions & 27 deletions internal/report/store_memory.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
package report

import (
"encoding/json"
"errors"
"fmt"
"strings"

"golang.org/x/exp/maps"

"github.com/kubewarden/audit-scanner/internal/constants"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
Expand Down Expand Up @@ -134,27 +131,3 @@ func (s *MemoryPolicyReportStore) SaveClusterPolicyReport(report *ClusterPolicyR
latestReport.Results = report.Results
return s.updateClusterPolicyReport(&latestReport)
}

func (s *MemoryPolicyReportStore) listPolicyReports() ([]PolicyReport, error) { //nolint:unparam // respect the interface
return maps.Values(s.prCache), nil
}

func (s *MemoryPolicyReportStore) ToJSON() (string, error) {
recapJSON := make(map[string]interface{})
clusterReport, err := s.GetClusterPolicyReport(constants.DefaultClusterwideReportName)
if err != nil {
log.Error().Err(err).Msg("error fetching ClusterPolicyReport. Ignoring this error to allow user to read the namespaced reports")
}
recapJSON["cluster"] = clusterReport
nsReports, err := s.listPolicyReports()
if err != nil {
return "", err
}
recapJSON["namespaces"] = nsReports

marshaled, err := json.Marshal(recapJSON)
if err != nil {
return "", err
}
return string(marshaled), nil
}
16 changes: 6 additions & 10 deletions internal/scanner/scanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import (
"net/url"
"os"

reportLogger "github.com/kubewarden/audit-scanner/internal/log"

"github.com/kubewarden/audit-scanner/internal/constants"
"github.com/kubewarden/audit-scanner/internal/report"
"github.com/kubewarden/audit-scanner/internal/resources"
Expand Down Expand Up @@ -49,6 +51,7 @@ type Scanner struct {
policiesFetcher PoliciesFetcher
resourcesFetcher ResourcesFetcher
reportStore report.PolicyReportStore
reportLogger reportLogger.PolicyReportLogger
// http client used to make requests against the Policy Server
httpClient http.Client
outputScan bool
Expand Down Expand Up @@ -112,6 +115,7 @@ func NewScanner(
policiesFetcher: policiesFetcher,
resourcesFetcher: resourcesFetcher,
reportStore: store,
reportLogger: reportLogger.PolicyReportLogger{},
httpClient: httpClient,
outputScan: outputScan,
}, nil
Expand Down Expand Up @@ -180,11 +184,7 @@ func (s *Scanner) ScanNamespace(nsName string) error {
log.Info().Str("namespace", nsName).Msg("namespace scan finished")

if s.outputScan {
str, err := s.reportStore.ToJSON()
if err != nil {
log.Error().Err(err).Msg("error marshaling reportStore to JSON")
}
fmt.Println(str) //nolint:forbidigo
s.reportLogger.LogPolicyReport(&namespacedsReport)
}

return nil
Expand Down Expand Up @@ -251,11 +251,7 @@ func (s *Scanner) ScanClusterWideResources() error {
log.Info().Msg("clusterwide resources scan finished")

if s.outputScan {
str, err := s.reportStore.ToJSON()
if err != nil {
log.Error().Err(err).Msg("error marshaling reportStore to JSON")
}
fmt.Println(str) //nolint:forbidigo
s.reportLogger.LogClusterPolicyReport(&clusterReport)
}

return nil
Expand Down

0 comments on commit be52c2d

Please sign in to comment.