istio.io/istio@v0.0.0-20240520182934-d79c90f27776/tests/fuzz/autoregistration_controller_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  	"fmt"
    19  	"time"
    20  
    21  	fuzz "github.com/AdaLogics/go-fuzz-headers"
    22  
    23  	"istio.io/api/networking/v1alpha3"
    24  	"istio.io/istio/pilot/pkg/autoregistration"
    25  	"istio.io/istio/pilot/pkg/config/memory"
    26  	"istio.io/istio/pilot/pkg/model"
    27  	"istio.io/istio/pkg/config"
    28  	"istio.io/istio/pkg/config/schema/collections"
    29  	"istio.io/istio/pkg/config/schema/gvk"
    30  	"istio.io/istio/pkg/keepalive"
    31  )
    32  
    33  type fakeConn struct {
    34  	proxy    *model.Proxy
    35  	connTime time.Time
    36  	stopped  bool
    37  }
    38  
    39  func makeConn(proxy *model.Proxy, connTime time.Time) *fakeConn {
    40  	return &fakeConn{proxy: proxy, connTime: connTime}
    41  }
    42  
    43  func (f *fakeConn) ID() string {
    44  	return fmt.Sprintf("%s-%v", f.proxy.IPAddresses[0], f.connTime)
    45  }
    46  
    47  func (f *fakeConn) Proxy() *model.Proxy {
    48  	return f.proxy
    49  }
    50  
    51  func (f *fakeConn) ConnectedAt() time.Time {
    52  	return f.connTime
    53  }
    54  
    55  func (f *fakeConn) Stop() {
    56  	f.stopped = true
    57  }
    58  
    59  var (
    60  	// A valid WorkloadGroup.
    61  	// This can be modified to have pseudo-random
    62  	// values for more randomization.
    63  	tmplA = &v1alpha3.WorkloadGroup{
    64  		Template: &v1alpha3.WorkloadEntry{
    65  			Ports:          map[string]uint32{"http": 80},
    66  			Labels:         map[string]string{"app": "a"},
    67  			Network:        "nw0",
    68  			Locality:       "reg0/zone0/subzone0",
    69  			Weight:         1,
    70  			ServiceAccount: "sa-a",
    71  		},
    72  	}
    73  	// A valid Config.
    74  	// This can be modified to have pseudo-random
    75  	// values for more randomization.
    76  	wgA = config.Config{
    77  		Meta: config.Meta{
    78  			GroupVersionKind: gvk.WorkloadGroup,
    79  			Namespace:        "a",
    80  			Name:             "wg-a",
    81  			Labels: map[string]string{
    82  				"grouplabel": "notonentry",
    83  			},
    84  		},
    85  		Spec:   tmplA,
    86  		Status: nil,
    87  	}
    88  )
    89  
    90  // FuzzWE implements a fuzzer that targets several apis
    91  // in the workloadentry package. It does so by setting
    92  // up a workloadentry controller with a proxy with
    93  // pseudo-random values.
    94  // The fuzzer then uses the controller to test:
    95  // 1: OnConnect
    96  // 2: OnDisconnect
    97  // 3: QueueWorkloadEntryHealth
    98  func FuzzWE(data []byte) int {
    99  	f := fuzz.NewConsumer(data)
   100  	proxy := &model.Proxy{}
   101  	err := f.GenerateStruct(proxy)
   102  	if err != nil {
   103  		return 0
   104  	}
   105  	if !proxy.FuzzValidate() {
   106  		return 0
   107  	}
   108  
   109  	store := memory.NewController(memory.Make(collections.All))
   110  	c := autoregistration.NewController(store, "", keepalive.Infinity)
   111  	err = createStore(store, wgA)
   112  	if err != nil {
   113  		fmt.Println(err)
   114  		return 0
   115  	}
   116  	stop := make(chan struct{})
   117  	go c.Run(stop)
   118  	defer close(stop)
   119  
   120  	conn := makeConn(proxy, time.Now())
   121  	err = c.OnConnect(conn)
   122  	if err != nil {
   123  		return 0
   124  	}
   125  	c.OnDisconnect(conn)
   126  
   127  	he := autoregistration.HealthEvent{}
   128  	err = f.GenerateStruct(&he)
   129  	if err != nil {
   130  		return 0
   131  	}
   132  	c.QueueWorkloadEntryHealth(proxy, he)
   133  
   134  	return 1
   135  }
   136  
   137  // Helper function to create a store.
   138  func createStore(store model.ConfigStoreController, cfg config.Config) error {
   139  	if _, err := store.Create(cfg); err != nil {
   140  		return err
   141  	}
   142  	return nil
   143  }