mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-29 02:45:06 +00:00
chore: add mocks to mutate fuzzer (#8102)
Signed-off-by: AdamKorcz <adam@adalogics.com>
This commit is contained in:
parent
04bc4ed7c6
commit
da3531a0c0
1 changed files with 354 additions and 4 deletions
|
@ -4,16 +4,29 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
apiextv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
openapiv2 "github.com/google/gnostic-models/openapiv2"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/client-go/dynamic"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
eventsv1 "k8s.io/client-go/kubernetes/typed/events/v1"
|
||||
|
||||
kyverno "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/autogen"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/config"
|
||||
"github.com/kyverno/kyverno/pkg/engine/adapters"
|
||||
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||
|
@ -296,14 +309,29 @@ func createRules(ff *fuzz.ConsumeFuzzer) []kyverno.Rule {
|
|||
if err != nil {
|
||||
return rules
|
||||
}
|
||||
var (
|
||||
wg sync.WaitGroup
|
||||
m sync.Mutex
|
||||
)
|
||||
for i := 0; i < noOfRules%100; i++ {
|
||||
rule, err := createRule(ff)
|
||||
ruleBytes, err := ff.GetBytes()
|
||||
if err != nil {
|
||||
return rules
|
||||
}
|
||||
|
||||
rules = append(rules, *rule)
|
||||
wg.Add(1)
|
||||
ff1 := fuzz.NewConsumer(ruleBytes)
|
||||
go func(ff2 *fuzz.ConsumeFuzzer) {
|
||||
defer wg.Done()
|
||||
rule, err := createRule(ff2)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
m.Lock()
|
||||
rules = append(rules, *rule)
|
||||
m.Unlock()
|
||||
}(ff1)
|
||||
}
|
||||
wg.Wait()
|
||||
return rules
|
||||
}
|
||||
|
||||
|
@ -593,11 +621,12 @@ func FuzzMutateTest(f *testing.F) {
|
|||
if err != nil {
|
||||
t.Skip()
|
||||
}
|
||||
fuzzInterface := FuzzInterface{ff: ff}
|
||||
e := NewEngine(
|
||||
fuzzCfg,
|
||||
config.NewDefaultMetricsConfiguration(),
|
||||
fuzzJp,
|
||||
adapters.Client(nil),
|
||||
adapters.Client(fuzzInterface),
|
||||
factories.DefaultRegistryClientFactory(adapters.RegistryClient(nil), nil),
|
||||
imageverifycache.DisabledImageVerifyCache(),
|
||||
factories.DefaultContextLoaderFactory(nil),
|
||||
|
@ -610,3 +639,324 @@ func FuzzMutateTest(f *testing.F) {
|
|||
)
|
||||
})
|
||||
}
|
||||
|
||||
type FuzzInterface struct {
|
||||
ff *fuzz.ConsumeFuzzer
|
||||
}
|
||||
|
||||
func (fi FuzzInterface) GetKubeClient() kubernetes.Interface {
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
func (fi FuzzInterface) GetEventsInterface() eventsv1.EventsV1Interface {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (fi FuzzInterface) GetDynamicInterface() dynamic.Interface {
|
||||
return DynamicFuzz{
|
||||
ff: fi.ff,
|
||||
}
|
||||
}
|
||||
|
||||
func (fi FuzzInterface) Discovery() dclient.IDiscovery {
|
||||
return FuzzIDiscovery{ff: fi.ff}
|
||||
}
|
||||
|
||||
func (fi FuzzInterface) SetDiscovery(discoveryClient dclient.IDiscovery) {
|
||||
|
||||
}
|
||||
|
||||
func (fi FuzzInterface) RawAbsPath(ctx context.Context, path string, method string, dataReader io.Reader) ([]byte, error) {
|
||||
return []byte("fuzz"), fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func (fi FuzzInterface) GetResource(ctx context.Context, apiVersion string, kind string, namespace string, name string, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func (fi FuzzInterface) PatchResource(ctx context.Context, apiVersion string, kind string, namespace string, name string, patch []byte) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func (fi FuzzInterface) ListResource(ctx context.Context, apiVersion string, kind string, namespace string, lselector *metav1.LabelSelector) (*unstructured.UnstructuredList, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func (fi FuzzInterface) DeleteResource(ctx context.Context, apiVersion string, kind string, namespace string, name string, dryRun bool) error {
|
||||
return fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func (fi FuzzInterface) CreateResource(ctx context.Context, apiVersion string, kind string, namespace string, obj interface{}, dryRun bool) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func (fi FuzzInterface) UpdateResource(ctx context.Context, apiVersion string, kind string, namespace string, obj interface{}, dryRun bool, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func (fi FuzzInterface) UpdateStatusResource(ctx context.Context, apiVersion string, kind string, namespace string, obj interface{}, dryRun bool) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func (fi FuzzInterface) ApplyResource(ctx context.Context, apiVersion string, kind string, namespace string, name string, obj interface{}, dryRun bool, fieldManager string, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
func (fi FuzzInterface) ApplyStatusResource(ctx context.Context, apiVersion string, kind string, namespace string, name string, obj interface{}, dryRun bool, fieldManager string) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
type FuzzIDiscovery struct {
|
||||
ff *fuzz.ConsumeFuzzer
|
||||
}
|
||||
|
||||
func (fid FuzzIDiscovery) FindResources(group, version, kind, subresource string) (map[dclient.TopLevelApiDescription]metav1.APIResource, error) {
|
||||
noOfRes, err := fid.ff.GetInt()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[dclient.TopLevelApiDescription]metav1.APIResource)
|
||||
for i := 0; i < noOfRes%10; i++ {
|
||||
gvGroup, err := GetK8sString(fid.ff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gvVersion, err := GetK8sString(fid.ff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gvResource, err := GetK8sString(fid.ff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
topLevelKind, err := GetK8sString(fid.ff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
topLevelResource, err := GetK8sString(fid.ff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
topLevelSubResource, err := GetK8sString(fid.ff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gvr := schema.GroupVersionResource{
|
||||
Group: gvGroup,
|
||||
Version: gvVersion,
|
||||
Resource: gvResource,
|
||||
}
|
||||
topLevel := dclient.TopLevelApiDescription{
|
||||
GroupVersion: gvr.GroupVersion(),
|
||||
Kind: topLevelKind,
|
||||
Resource: topLevelResource,
|
||||
SubResource: topLevelSubResource,
|
||||
}
|
||||
apiResource := metav1.APIResource{}
|
||||
apiName, err := GetK8sString(fid.ff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
apiResource.Name = apiName
|
||||
|
||||
apiSingularName, err := GetK8sString(fid.ff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
apiResource.SingularName = apiSingularName
|
||||
|
||||
namespaced, err := fid.ff.GetBool()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
apiResource.Namespaced = namespaced
|
||||
|
||||
setGroup, err := fid.ff.GetBool()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if setGroup {
|
||||
apiGroup, err := GetK8sString(fid.ff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
apiResource.Group = apiGroup
|
||||
}
|
||||
|
||||
verbs := []string{"get", "list", "watch", "create", "update", "patch", "delete", "deletecollection", "proxy"}
|
||||
apiResource.Verbs = verbs
|
||||
|
||||
setShortNames, err := fid.ff.GetBool()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var shortNames = make([]string, 0)
|
||||
if setShortNames {
|
||||
fid.ff.CreateSlice(&shortNames)
|
||||
apiResource.ShortNames = shortNames
|
||||
}
|
||||
setCategories, err := fid.ff.GetBool()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var categories = make([]string, 0)
|
||||
if setCategories {
|
||||
fid.ff.CreateSlice(&categories)
|
||||
apiResource.Categories = categories
|
||||
}
|
||||
|
||||
setStorageHash, err := fid.ff.GetBool()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if setStorageHash {
|
||||
storageHash, err := fid.ff.GetString()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
apiResource.StorageVersionHash = storageHash
|
||||
}
|
||||
m[topLevel] = apiResource
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
func (fid FuzzIDiscovery) GetGVRFromGVK(schema.GroupVersionKind) (schema.GroupVersionResource, error) {
|
||||
return schema.GroupVersionResource{}, fmt.Errorf("Not implemented")
|
||||
|
||||
}
|
||||
|
||||
func (fid FuzzIDiscovery) GetGVKFromGVR(schema.GroupVersionResource) (schema.GroupVersionKind, error) {
|
||||
return schema.GroupVersionKind{}, fmt.Errorf("Not implemented")
|
||||
|
||||
}
|
||||
|
||||
func (fid FuzzIDiscovery) OpenAPISchema() (*openapiv2.Document, error) {
|
||||
b, err := fid.ff.GetBytes()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return openapiv2.ParseDocument(b)
|
||||
}
|
||||
|
||||
func (fid FuzzIDiscovery) CachedDiscoveryInterface() discovery.CachedDiscoveryInterface {
|
||||
return nil
|
||||
}
|
||||
|
||||
type DynamicFuzz struct {
|
||||
ff *fuzz.ConsumeFuzzer
|
||||
}
|
||||
|
||||
func (df DynamicFuzz) Resource(resource schema.GroupVersionResource) dynamic.NamespaceableResourceInterface {
|
||||
return FuzzNamespaceableResource{
|
||||
ff: df.ff,
|
||||
}
|
||||
}
|
||||
|
||||
type FuzzResource struct {
|
||||
ff *fuzz.ConsumeFuzzer
|
||||
}
|
||||
|
||||
func (fr FuzzResource) Create(ctx context.Context, obj *unstructured.Unstructured, options metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzResource) Update(ctx context.Context, obj *unstructured.Unstructured, options metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzResource) UpdateStatus(ctx context.Context, obj *unstructured.Unstructured, options metav1.UpdateOptions) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzResource) Delete(ctx context.Context, name string, options metav1.DeleteOptions, subresources ...string) error {
|
||||
return fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzResource) DeleteCollection(ctx context.Context, options metav1.DeleteOptions, listOptions metav1.ListOptions) error {
|
||||
return fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzResource) Get(ctx context.Context, name string, options metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
resource, err := createUnstructuredObject(fr.ff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resource, fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzResource) List(ctx context.Context, opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzResource) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzResource) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, options metav1.PatchOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzResource) Apply(ctx context.Context, name string, obj *unstructured.Unstructured, options metav1.ApplyOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzResource) ApplyStatus(ctx context.Context, name string, obj *unstructured.Unstructured, options metav1.ApplyOptions) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
||||
type FuzzNamespaceableResource struct {
|
||||
ff *fuzz.ConsumeFuzzer
|
||||
}
|
||||
|
||||
func (fnr FuzzNamespaceableResource) Namespace(string) dynamic.ResourceInterface {
|
||||
return FuzzResource{
|
||||
ff: fnr.ff,
|
||||
}
|
||||
}
|
||||
func (fr FuzzNamespaceableResource) Create(ctx context.Context, obj *unstructured.Unstructured, options metav1.CreateOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzNamespaceableResource) Update(ctx context.Context, obj *unstructured.Unstructured, options metav1.UpdateOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzNamespaceableResource) UpdateStatus(ctx context.Context, obj *unstructured.Unstructured, options metav1.UpdateOptions) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzNamespaceableResource) Delete(ctx context.Context, name string, options metav1.DeleteOptions, subresources ...string) error {
|
||||
return fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzNamespaceableResource) DeleteCollection(ctx context.Context, options metav1.DeleteOptions, listOptions metav1.ListOptions) error {
|
||||
return fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzNamespaceableResource) Get(ctx context.Context, name string, options metav1.GetOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
resource, err := createUnstructuredObject(fr.ff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return resource, nil
|
||||
}
|
||||
func (fr FuzzNamespaceableResource) List(ctx context.Context, opts metav1.ListOptions) (*unstructured.UnstructuredList, error) {
|
||||
var objs []unstructured.Unstructured
|
||||
objs = make([]unstructured.Unstructured, 0)
|
||||
noOfObjs, err := fr.ff.GetInt()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < noOfObjs%10; i++ {
|
||||
obj, err := createUnstructuredObject(fr.ff)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
objs = append(objs, *obj)
|
||||
}
|
||||
return &unstructured.UnstructuredList{
|
||||
Object: map[string]interface{}{"kind": "List", "apiVersion": "v1"},
|
||||
Items: objs,
|
||||
}, nil
|
||||
}
|
||||
func (fr FuzzNamespaceableResource) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzNamespaceableResource) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, options metav1.PatchOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzNamespaceableResource) Apply(ctx context.Context, name string, obj *unstructured.Unstructured, options metav1.ApplyOptions, subresources ...string) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
func (fr FuzzNamespaceableResource) ApplyStatus(ctx context.Context, name string, obj *unstructured.Unstructured, options metav1.ApplyOptions) (*unstructured.Unstructured, error) {
|
||||
return nil, fmt.Errorf("Not implemented")
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue