istio.io/istio@v0.0.0-20240520182934-d79c90f27776/tests/fuzz/aggregate_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  // nolint: revive
    16  package fuzz
    17  
    18  import (
    19  	"fmt"
    20  
    21  	fuzz "github.com/AdaLogics/go-fuzz-headers"
    22  
    23  	meshconfig "istio.io/api/mesh/v1alpha1"
    24  	"istio.io/istio/pilot/pkg/serviceregistry"
    25  	"istio.io/istio/pilot/pkg/serviceregistry/aggregate"
    26  )
    27  
    28  var meshHolder fuzzMeshConfigHolder
    29  
    30  type fuzzMeshConfigHolder struct {
    31  	trustDomainAliases []string
    32  }
    33  
    34  func (mh fuzzMeshConfigHolder) Mesh() *meshconfig.MeshConfig {
    35  	return &meshconfig.MeshConfig{
    36  		TrustDomainAliases: mh.trustDomainAliases,
    37  	}
    38  }
    39  
    40  // FuzzAggregateController implements a fuzzer
    41  // that targets the add and delete registry apis
    42  // of the aggregate controller. It does so by
    43  // creating a controller with a pseudo-random
    44  // Options{} and create pseudo-random service
    45  // registries and deleting them.
    46  func FuzzAggregateController(data []byte) int {
    47  	ops := map[int]string{
    48  		0: "AddRegistry",
    49  		1: "DeleteRegistry",
    50  	}
    51  	maxOps := 2
    52  	f := fuzz.NewConsumer(data)
    53  	opts := aggregate.Options{}
    54  	err := f.GenerateStruct(&opts)
    55  	if err != nil {
    56  		return 0
    57  	}
    58  	opts.MeshHolder = meshHolder
    59  	c := aggregate.NewController(opts)
    60  
    61  	iterations, err := f.GetInt()
    62  	if err != nil {
    63  		return 0
    64  	}
    65  	for i := 0; i < iterations%30; i++ {
    66  		opType, err := f.GetInt()
    67  		if err != nil {
    68  			return 0
    69  		}
    70  		switch ops[opType%maxOps] {
    71  		case "AddRegistry":
    72  			err = runAddRegistry(f, c)
    73  		case "DeleteRegistry":
    74  			err = runDeleteRegistry(f, c)
    75  		}
    76  		if err != nil {
    77  			return 0
    78  		}
    79  	}
    80  	return 1
    81  }
    82  
    83  // Helper function to create a registry.
    84  func runAddRegistry(f *fuzz.ConsumeFuzzer, c *aggregate.Controller) error {
    85  	registry := serviceregistry.Simple{}
    86  	err := f.GenerateStruct(&registry)
    87  	if err != nil {
    88  		return err
    89  	}
    90  	if registry.DiscoveryController == nil {
    91  		return fmt.Errorf("registry required")
    92  	}
    93  	c.AddRegistry(registry)
    94  	return nil
    95  }
    96  
    97  // Helper function to delete a registry.
    98  func runDeleteRegistry(f *fuzz.ConsumeFuzzer, c *aggregate.Controller) error {
    99  	registries := c.GetRegistries()
   100  	if len(registries) == 0 {
   101  		return fmt.Errorf("no registries")
   102  	}
   103  	index, err := f.GetInt()
   104  	if err != nil {
   105  		return err
   106  	}
   107  	selectedRegistry := registries[index%len(registries)]
   108  	c.DeleteRegistry(selectedRegistry.Cluster(), selectedRegistry.Provider())
   109  	return nil
   110  }