istio.io/istio@v0.0.0-20240520182934-d79c90f27776/tests/fuzz/config_validation_fuzzer.go (about)

     1  // Copyright Istio Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package fuzz
    16  
    17  import (
    18  	fuzz "github.com/AdaLogics/go-fuzz-headers"
    19  	apimeta "k8s.io/apimachinery/pkg/api/meta"
    20  	"k8s.io/apimachinery/pkg/runtime/schema"
    21  
    22  	extensions "istio.io/api/extensions/v1alpha1"
    23  	networking "istio.io/api/networking/v1alpha3"
    24  	networkingv1beta1 "istio.io/api/networking/v1beta1"
    25  	security_beta "istio.io/api/security/v1beta1"
    26  	telemetry "istio.io/api/telemetry/v1alpha1"
    27  	"istio.io/istio/pilot/pkg/config/kube/crdclient"
    28  	"istio.io/istio/pkg/config"
    29  	"istio.io/istio/pkg/config/schema/collections"
    30  	"istio.io/istio/pkg/config/validation"
    31  	"istio.io/istio/pkg/config/validation/envoyfilter"
    32  	"istio.io/istio/pkg/kube"
    33  )
    34  
    35  func FuzzConfigValidation(data []byte) int {
    36  	f := fuzz.NewConsumer(data)
    37  	configIndex, err := f.GetInt()
    38  	if err != nil {
    39  		return -1
    40  	}
    41  
    42  	r := collections.Pilot.All()[configIndex%len(collections.Pilot.All())]
    43  	gvk := r.GroupVersionKind()
    44  	kgvk := schema.GroupVersionKind{
    45  		Group:   gvk.Group,
    46  		Version: gvk.Version,
    47  		Kind:    gvk.Kind,
    48  	}
    49  	object, err := kube.IstioScheme.New(kgvk)
    50  	if err != nil {
    51  		return 0
    52  	}
    53  	_, err = apimeta.TypeAccessor(object)
    54  	if err != nil {
    55  		return 0
    56  	}
    57  
    58  	err = f.GenerateStruct(&object)
    59  	if err != nil {
    60  		return 0
    61  	}
    62  
    63  	iobj := crdclient.TranslateObject(object, gvk, "cluster.local")
    64  	_, _ = r.ValidateConfig(iobj)
    65  	return 1
    66  }
    67  
    68  // FuzzConfigValidation2 implements a second fuzzer for config validation.
    69  // The fuzzer targets the same API as FuzzConfigValidation above,
    70  // but its approach to creating a fuzzed config is a bit different
    71  // in that it utilizes Istio APIs to generate a Spec from json.
    72  // We currently run both continuously to compare their performance.
    73  func FuzzConfigValidation2(data []byte) int {
    74  	f := fuzz.NewConsumer(data)
    75  	configIndex, err := f.GetInt()
    76  	if err != nil {
    77  		return -1
    78  	}
    79  	r := collections.Pilot.All()[configIndex%len(collections.Pilot.All())]
    80  
    81  	spec, err := r.NewInstance()
    82  	if err != nil {
    83  		return 0
    84  	}
    85  	jsonData, err := f.GetString()
    86  	if err != nil {
    87  		return 0
    88  	}
    89  	err = config.ApplyJSON(spec, jsonData)
    90  	if err != nil {
    91  		return 0
    92  	}
    93  
    94  	m := config.Meta{}
    95  	err = f.GenerateStruct(&m)
    96  	if err != nil {
    97  		return 0
    98  	}
    99  
   100  	gvk := r.GroupVersionKind()
   101  	m.GroupVersionKind = gvk
   102  
   103  	_, _ = r.ValidateConfig(config.Config{
   104  		Meta: m,
   105  		Spec: spec,
   106  	})
   107  	return 1
   108  }
   109  
   110  func FuzzConfigValidation3(data []byte) int {
   111  	if len(data) < 10 {
   112  		return 0
   113  	}
   114  	f := fuzz.NewConsumer(data)
   115  	c := config.Config{}
   116  	err := f.GenerateStruct(&c)
   117  	if err != nil {
   118  		return 0
   119  	}
   120  	targetNumber, err := f.GetInt()
   121  	if err != nil {
   122  		return 0
   123  	}
   124  	numberOfTargets := targetNumber % 13
   125  	switch numberOfTargets {
   126  	case 0:
   127  		in := &networking.Gateway{}
   128  		err = f.GenerateStruct(in)
   129  		if err != nil {
   130  			return 0
   131  		}
   132  		c.Spec = in
   133  		_, _ = validation.ValidateGateway(c)
   134  	case 1:
   135  		in := &networking.TrafficPolicy{}
   136  		err = f.GenerateStruct(in)
   137  		if err != nil {
   138  			return 0
   139  		}
   140  		c.Spec = in
   141  		_, _ = validation.ValidateDestinationRule(c)
   142  	case 2:
   143  		in := &networking.EnvoyFilter_EnvoyConfigObjectPatch{}
   144  		err = f.GenerateStruct(in)
   145  		if err != nil {
   146  			return 0
   147  		}
   148  		c.Spec = in
   149  		_, _ = envoyfilter.ValidateEnvoyFilter(c)
   150  	case 3:
   151  		in := &networking.Sidecar{}
   152  		err = f.GenerateStruct(in)
   153  		if err != nil {
   154  			return 0
   155  		}
   156  		c.Spec = in
   157  		_, _ = validation.ValidateSidecar(c)
   158  	case 4:
   159  		in := &security_beta.AuthorizationPolicy{}
   160  		err = f.GenerateStruct(in)
   161  		if err != nil {
   162  			return 0
   163  		}
   164  		c.Spec = in
   165  		_, _ = validation.ValidateAuthorizationPolicy(c)
   166  	case 5:
   167  		in := &security_beta.RequestAuthentication{}
   168  		err = f.GenerateStruct(in)
   169  		if err != nil {
   170  			return 0
   171  		}
   172  		c.Spec = in
   173  		_, _ = validation.ValidateRequestAuthentication(c)
   174  	case 6:
   175  		in := &security_beta.PeerAuthentication{}
   176  		err = f.GenerateStruct(in)
   177  		if err != nil {
   178  			return 0
   179  		}
   180  		c.Spec = in
   181  		_, _ = validation.ValidatePeerAuthentication(c)
   182  	case 7:
   183  		in := &networking.VirtualService{}
   184  		err = f.GenerateStruct(in)
   185  		if err != nil {
   186  			return 0
   187  		}
   188  		c.Spec = in
   189  		_, _ = validation.ValidateVirtualService(c)
   190  	case 8:
   191  		in := &networking.WorkloadEntry{}
   192  		err = f.GenerateStruct(in)
   193  		if err != nil {
   194  			return 0
   195  		}
   196  		c.Spec = in
   197  		_, _ = validation.ValidateWorkloadEntry(c)
   198  	case 9:
   199  		in := &networking.ServiceEntry{}
   200  		err = f.GenerateStruct(in)
   201  		if err != nil {
   202  			return 0
   203  		}
   204  		c.Spec = in
   205  		_, _ = validation.ValidateServiceEntry(c)
   206  	case 10:
   207  		in := &networkingv1beta1.ProxyConfig{}
   208  		err = f.GenerateStruct(in)
   209  		if err != nil {
   210  			return 0
   211  		}
   212  		c.Spec = in
   213  		_, _ = validation.ValidateProxyConfig(c)
   214  	case 11:
   215  		in := &telemetry.Telemetry{}
   216  		err = f.GenerateStruct(in)
   217  		if err != nil {
   218  			return 0
   219  		}
   220  		c.Spec = in
   221  		_, _ = validation.ValidateTelemetry(c)
   222  	case 12:
   223  		in := &extensions.WasmPlugin{}
   224  		err = f.GenerateStruct(in)
   225  		if err != nil {
   226  			return 0
   227  		}
   228  		c.Spec = in
   229  		_, _ = validation.ValidateWasmPlugin(c)
   230  	}
   231  	return 1
   232  }