1
0
Fork 0
mirror of https://github.com/kyverno/kyverno.git synced 2025-03-05 07:26:55 +00:00
kyverno/pkg/webhooks/handlers/dump.go
2023-04-06 14:28:13 +00:00

122 lines
4.1 KiB
Go

package handlers
import (
"context"
"strings"
"time"
"github.com/go-logr/logr"
admissionutils "github.com/kyverno/kyverno/pkg/utils/admission"
kubeutils "github.com/kyverno/kyverno/pkg/utils/kube"
authenticationv1 "k8s.io/api/authentication/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/types"
)
func (inner AdmissionHandler) WithDump(
enabled bool,
) AdmissionHandler {
if !enabled {
return inner
}
return inner.withDump().WithTrace("DUMP")
}
func (inner AdmissionHandler) withDump() AdmissionHandler {
return func(ctx context.Context, logger logr.Logger, request AdmissionRequest, startTime time.Time) AdmissionResponse {
response := inner(ctx, logger, request, startTime)
dumpPayload(logger, request, response)
return response
}
}
func dumpPayload(
logger logr.Logger,
request AdmissionRequest,
response AdmissionResponse,
) {
reqPayload, err := newAdmissionRequestPayload(request)
if err != nil {
logger.Error(err, "Failed to extract resources")
} else {
logger = logger.WithValues("admission.response", response, "admission.request", reqPayload)
logger.Info("admission request dump")
}
}
// admissionRequestPayload holds a copy of the AdmissionRequest payload
type admissionRequestPayload struct {
UID types.UID `json:"uid"`
Kind metav1.GroupVersionKind `json:"kind"`
Resource metav1.GroupVersionResource `json:"resource"`
SubResource string `json:"subResource,omitempty"`
RequestKind *metav1.GroupVersionKind `json:"requestKind,omitempty"`
RequestResource *metav1.GroupVersionResource `json:"requestResource,omitempty"`
RequestSubResource string `json:"requestSubResource,omitempty"`
Name string `json:"name,omitempty"`
Namespace string `json:"namespace,omitempty"`
Operation string `json:"operation"`
UserInfo authenticationv1.UserInfo `json:"userInfo"`
Roles []string `json:"roles"`
ClusterRoles []string `json:"clusterRoles"`
Object unstructured.Unstructured `json:"object,omitempty"`
OldObject unstructured.Unstructured `json:"oldObject,omitempty"`
DryRun *bool `json:"dryRun,omitempty"`
Options unstructured.Unstructured `json:"options,omitempty"`
}
func newAdmissionRequestPayload(
request AdmissionRequest,
) (*admissionRequestPayload, error) {
newResource, oldResource, err := admissionutils.ExtractResources(nil, request.AdmissionRequest)
if err != nil {
return nil, err
}
options := new(unstructured.Unstructured)
if request.Options.Raw != nil {
options, err = kubeutils.BytesToUnstructured(request.Options.Raw)
if err != nil {
return nil, err
}
}
return redactPayload(&admissionRequestPayload{
UID: request.UID,
Kind: request.Kind,
Resource: request.Resource,
SubResource: request.SubResource,
RequestKind: request.RequestKind,
RequestResource: request.RequestResource,
RequestSubResource: request.RequestSubResource,
Name: request.Name,
Namespace: request.Namespace,
Operation: string(request.Operation),
UserInfo: request.UserInfo,
Roles: request.Roles,
ClusterRoles: request.ClusterRoles,
Object: newResource,
OldObject: oldResource,
DryRun: request.DryRun,
Options: *options,
})
}
func redactPayload(payload *admissionRequestPayload) (*admissionRequestPayload, error) {
if strings.EqualFold(payload.Kind.Kind, "Secret") {
if payload.Object.Object != nil {
obj, err := kubeutils.RedactSecret(&payload.Object)
if err != nil {
return nil, err
}
payload.Object = obj
}
if payload.OldObject.Object != nil {
oldObj, err := kubeutils.RedactSecret(&payload.OldObject)
if err != nil {
return nil, err
}
payload.OldObject = oldObj
}
}
return payload, nil
}