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 }