mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-06 07:57:07 +00:00
feat: add reporting to validating admission handler (#12090)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
9e8b655f6f
commit
4a4aef54d3
3 changed files with 69 additions and 11 deletions
|
@ -94,7 +94,7 @@ func initMetricsFlags() {
|
|||
}
|
||||
|
||||
func initKubeconfigFlags(qps float64, burst int, eventsQPS float64, eventsBurst int) {
|
||||
if f := flag.CommandLine.Lookup("kubeconfig"); f == nil {
|
||||
if f := flag.Lookup("kubeconfig"); f == nil {
|
||||
flag.StringVar(&kubeconfig, "kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.")
|
||||
}
|
||||
flag.Float64Var(&clientRateLimitQPS, "clientRateLimitQPS", qps, "Configure the maximum QPS to the Kubernetes API server from Kyverno. Uses the client default if zero.")
|
||||
|
@ -149,8 +149,8 @@ func initReportingFlags() {
|
|||
}
|
||||
|
||||
func lookupKubeconfigFlag() {
|
||||
if f := flag.CommandLine.Lookup("kubeconfig"); f != nil {
|
||||
kubeconfig = flag.CommandLine.Lookup("kubeconfig").Value.String()
|
||||
if f := flag.Lookup("kubeconfig"); f != nil {
|
||||
kubeconfig = f.Value.String()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -605,7 +605,6 @@ func main() {
|
|||
matching.NewMatcher(),
|
||||
)
|
||||
}
|
||||
voplHandlers := vpol.New(celEngine, contextProvider)
|
||||
ephrs, err := breaker.StartAdmissionReportsCounter(signalCtx, setup.MetadataClient)
|
||||
if err != nil {
|
||||
setup.Logger.Error(err, "failed to start admission reports watcher")
|
||||
|
@ -640,6 +639,12 @@ func main() {
|
|||
setup.ReportingConfiguration,
|
||||
reportsBreaker,
|
||||
)
|
||||
voplHandlers := vpol.New(
|
||||
celEngine,
|
||||
contextProvider,
|
||||
setup.KyvernoClient,
|
||||
reportsBreaker,
|
||||
)
|
||||
exceptionHandlers := webhooksexception.NewHandlers(exception.ValidationOptions{
|
||||
Enabled: internal.PolicyExceptionEnabled(),
|
||||
Namespace: internal.ExceptionNamespace(),
|
||||
|
|
|
@ -6,24 +6,37 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/kyverno/kyverno/pkg/breaker"
|
||||
celengine "github.com/kyverno/kyverno/pkg/cel/engine"
|
||||
celpolicy "github.com/kyverno/kyverno/pkg/cel/policy"
|
||||
"github.com/kyverno/kyverno/pkg/client/clientset/versioned"
|
||||
engineapi "github.com/kyverno/kyverno/pkg/engine/api"
|
||||
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
|
||||
reportutils "github.com/kyverno/kyverno/pkg/utils/report"
|
||||
"github.com/kyverno/kyverno/pkg/webhooks/handlers"
|
||||
"go.uber.org/multierr"
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
)
|
||||
|
||||
type handler struct {
|
||||
context celpolicy.Context
|
||||
engine celengine.Engine
|
||||
kyvernoClient versioned.Interface
|
||||
reportsBreaker breaker.Breaker
|
||||
}
|
||||
|
||||
func New(engine celengine.Engine, context celpolicy.Context) *handler {
|
||||
func New(
|
||||
engine celengine.Engine,
|
||||
context celpolicy.Context,
|
||||
kyvernoClient versioned.Interface,
|
||||
reportsBreaker breaker.Breaker,
|
||||
) *handler {
|
||||
return &handler{
|
||||
context: context,
|
||||
engine: engine,
|
||||
kyvernoClient: kyvernoClient,
|
||||
reportsBreaker: reportsBreaker,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -35,10 +48,18 @@ func (h *handler) Validate(ctx context.Context, logger logr.Logger, request hand
|
|||
if err != nil {
|
||||
return admissionutils.Response(request.UID, err)
|
||||
}
|
||||
return admissionResponse(response, request)
|
||||
var group wait.Group
|
||||
defer group.Wait()
|
||||
group.Start(func() {
|
||||
err := h.admissionReport(ctx, response, request)
|
||||
if err != nil {
|
||||
logger.Error(err, "failed to create report")
|
||||
}
|
||||
})
|
||||
return h.admissionResponse(response, request)
|
||||
}
|
||||
|
||||
func admissionResponse(response celengine.EngineResponse, request handlers.AdmissionRequest) handlers.AdmissionResponse {
|
||||
func (h *handler) admissionResponse(response celengine.EngineResponse, request handlers.AdmissionRequest) handlers.AdmissionResponse {
|
||||
var errs []error
|
||||
var warnings []string
|
||||
for _, policy := range response.Policies {
|
||||
|
@ -65,3 +86,35 @@ func admissionResponse(response celengine.EngineResponse, request handlers.Admis
|
|||
}
|
||||
return admissionutils.Response(request.UID, multierr.Combine(errs...), warnings...)
|
||||
}
|
||||
|
||||
func (h *handler) admissionReport(ctx context.Context, response celengine.EngineResponse, request handlers.AdmissionRequest) error {
|
||||
object, oldObject, err := admissionutils.ExtractResources(nil, request.AdmissionRequest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if object.Object == nil {
|
||||
object = oldObject
|
||||
}
|
||||
responses := make([]engineapi.EngineResponse, 0, len(response.Policies))
|
||||
for _, r := range response.Policies {
|
||||
engineResponse := engineapi.EngineResponse{
|
||||
Resource: object,
|
||||
PolicyResponse: engineapi.PolicyResponse{
|
||||
Rules: r.Rules,
|
||||
},
|
||||
}
|
||||
engineResponse = engineResponse.WithPolicy(engineapi.NewValidatingPolicy(&r.Policy))
|
||||
responses = append(responses, engineResponse)
|
||||
}
|
||||
report := reportutils.BuildAdmissionReport(object, request.AdmissionRequest, responses...)
|
||||
if len(report.GetResults()) > 0 {
|
||||
err := h.reportsBreaker.Do(ctx, func(ctx context.Context) error {
|
||||
_, err := reportutils.CreateReport(ctx, report, h.kyvernoClient)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue