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 }