istio.io/istio@v0.0.0-20240520182934-d79c90f27776/tests/fuzz/pilot_model_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  	"errors"
    19  
    20  	fuzz "github.com/AdaLogics/go-fuzz-headers"
    21  
    22  	"istio.io/istio/pilot/pkg/model"
    23  	"istio.io/istio/pilot/pkg/serviceregistry/memory"
    24  	"istio.io/istio/pkg/config/host"
    25  	"istio.io/istio/pkg/config/mesh"
    26  	"istio.io/istio/pkg/config/protocol"
    27  	"istio.io/istio/pkg/slices"
    28  )
    29  
    30  var protocols = []protocol.Instance{
    31  	protocol.TCP,
    32  	protocol.UDP,
    33  	protocol.GRPC,
    34  	protocol.GRPCWeb,
    35  	protocol.HTTP,
    36  	protocol.HTTP_PROXY,
    37  	protocol.HTTP2,
    38  	protocol.HTTPS,
    39  	protocol.TLS,
    40  	protocol.Mongo,
    41  	protocol.Redis,
    42  	protocol.MySQL,
    43  }
    44  
    45  // Creates a new fuzzed ServiceInstance
    46  func NewSI(f *fuzz.ConsumeFuzzer) (*model.ServiceInstance, error) {
    47  	si := &model.ServiceInstance{}
    48  	err := f.GenerateStruct(si)
    49  	if err != nil {
    50  		return si, err
    51  	}
    52  	s, err := NewS(f)
    53  	if err != nil {
    54  		return si, err
    55  	}
    56  	p, err := createPort(f)
    57  	if err != nil {
    58  		return si, err
    59  	}
    60  	s.Ports = append(s.Ports, p)
    61  	si.ServicePort = p
    62  	si.Service = s
    63  	err = si.Validate()
    64  	if err != nil {
    65  		return si, err
    66  	}
    67  	return si, nil
    68  }
    69  
    70  // Gets a protocol from global var protocols
    71  func getProtocolInstance(f *fuzz.ConsumeFuzzer) (protocol.Instance, error) {
    72  	pIndex, err := f.GetInt()
    73  	if err != nil {
    74  		return protocol.Unsupported, errors.New("could not create protocolInstance")
    75  	}
    76  	i := protocols[pIndex%len(protocols)]
    77  	return i, nil
    78  }
    79  
    80  // Creates a new fuzzed Port
    81  func createPort(f *fuzz.ConsumeFuzzer) (*model.Port, error) {
    82  	p := &model.Port{}
    83  	name, err := f.GetString()
    84  	if err != nil {
    85  		return p, err
    86  	}
    87  	port, err := f.GetInt()
    88  	if err != nil {
    89  		return p, err
    90  	}
    91  	protocolinstance, err := getProtocolInstance(f)
    92  	if err != nil {
    93  		return p, err
    94  	}
    95  	p.Name = name
    96  	p.Port = port
    97  	p.Protocol = protocolinstance
    98  	return p, nil
    99  }
   100  
   101  // Creates a new fuzzed Port slice
   102  func createPorts(f *fuzz.ConsumeFuzzer) ([]*model.Port, error) {
   103  	ports := make([]*model.Port, 0, 20)
   104  	numberOfPorts, err := f.GetInt()
   105  	if err != nil {
   106  		return ports, err
   107  	}
   108  	// Maximum 20 ports:
   109  	maxPorts := numberOfPorts % 20
   110  	if maxPorts == 0 {
   111  		maxPorts = 1
   112  	}
   113  	for i := 0; i < maxPorts; i++ {
   114  		port, err := createPort(f)
   115  		if err != nil {
   116  			return ports, err
   117  		}
   118  		ports = append(ports, port)
   119  	}
   120  	return ports, nil
   121  }
   122  
   123  // Creates a new fuzzed Service
   124  func NewS(f *fuzz.ConsumeFuzzer) (*model.Service, error) {
   125  	s := &model.Service{}
   126  	err := f.GenerateStruct(s)
   127  	if err != nil {
   128  		return s, err
   129  	}
   130  	ports, err := createPorts(f)
   131  	if err != nil {
   132  		return s, err
   133  	}
   134  	s.Ports = ports
   135  	hostname, err := f.GetString()
   136  	if err != nil {
   137  		return s, err
   138  	}
   139  	s.Hostname = host.Name(hostname)
   140  	err = s.Validate()
   141  	if err != nil {
   142  		return s, err
   143  	}
   144  	return s, nil
   145  }
   146  
   147  // Creates an Environment with fuzzed values
   148  // and passes that to InitContext
   149  func FuzzInitContext(data []byte) int {
   150  	f := fuzz.NewConsumer(data)
   151  
   152  	// Create service instances
   153  	serviceInstances := make([]*model.ServiceInstance, 0, 20)
   154  	number, err := f.GetInt()
   155  	if err != nil {
   156  		return 0
   157  	}
   158  	// We allow a maximum of 20 service instances
   159  	numberOfS := number % 20
   160  	for i := 0; i < numberOfS; i++ {
   161  		si, err := NewSI(f)
   162  		if err != nil {
   163  			return 0
   164  		}
   165  		serviceInstances = append(serviceInstances, si)
   166  	}
   167  
   168  	// Create services
   169  	services := make([]*model.Service, 0, 20)
   170  	number, err = f.GetInt()
   171  	if err != nil {
   172  		return 0
   173  	}
   174  	// We allow a maximum of 20 services
   175  	numberOfS = number % 20
   176  	for i := 0; i < numberOfS; i++ {
   177  		s, err := NewS(f)
   178  		if err != nil {
   179  			return 0
   180  		}
   181  		services = append(services, s)
   182  	}
   183  
   184  	configString, err := f.GetString()
   185  	if err != nil {
   186  		return 0
   187  	}
   188  	m, err := mesh.ApplyMeshConfigDefaults(configString)
   189  	if err != nil {
   190  		return 0
   191  	}
   192  
   193  	env := &model.Environment{}
   194  	store := model.NewFakeStore()
   195  
   196  	env.ConfigStore = store
   197  	sd := memory.NewServiceDiscovery(services...)
   198  	sd.WantGetProxyServiceTargets = slices.Map(serviceInstances, model.ServiceInstanceToTarget)
   199  	env.ServiceDiscovery = sd
   200  
   201  	env.Watcher = mesh.NewFixedWatcher(m)
   202  	env.EndpointIndex = model.NewEndpointIndex(model.DisabledCache{})
   203  	env.Init()
   204  	pc := model.NewPushContext()
   205  	_ = pc.InitContext(env, nil, nil)
   206  	return 1
   207  }
   208  
   209  func FuzzBNMUnmarshalJSON(data []byte) int {
   210  	var bnm model.BootstrapNodeMetadata
   211  	_ = bnm.UnmarshalJSON(data)
   212  	return 1
   213  }