k8s.io/kubernetes@v1.29.3/pkg/apis/networking/fuzzer/fuzzer.go (about)

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package fuzzer
    18  
    19  import (
    20  	"fmt"
    21  	"net/netip"
    22  
    23  	fuzz "github.com/google/gofuzz"
    24  	runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
    25  	"k8s.io/kubernetes/pkg/apis/networking"
    26  	utilpointer "k8s.io/utils/pointer"
    27  )
    28  
    29  // Funcs returns the fuzzer functions for the networking api group.
    30  var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
    31  	return []interface{}{
    32  		func(np *networking.NetworkPolicyPeer, c fuzz.Continue) {
    33  			c.FuzzNoCustom(np) // fuzz self without calling this function again
    34  			// TODO: Implement a fuzzer to generate valid keys, values and operators for
    35  			// selector requirements.
    36  			if np.IPBlock != nil {
    37  				np.IPBlock = &networking.IPBlock{
    38  					CIDR:   "192.168.1.0/24",
    39  					Except: []string{"192.168.1.1/24", "192.168.1.2/24"},
    40  				}
    41  			}
    42  		},
    43  		func(np *networking.NetworkPolicy, c fuzz.Continue) {
    44  			c.FuzzNoCustom(np) // fuzz self without calling this function again
    45  			// TODO: Implement a fuzzer to generate valid keys, values and operators for
    46  			// selector requirements.
    47  			if len(np.Spec.PolicyTypes) == 0 {
    48  				np.Spec.PolicyTypes = []networking.PolicyType{networking.PolicyTypeIngress}
    49  			}
    50  		},
    51  		func(path *networking.HTTPIngressPath, c fuzz.Continue) {
    52  			c.FuzzNoCustom(path) // fuzz self without calling this function again
    53  			pathTypes := []networking.PathType{networking.PathTypeExact, networking.PathTypePrefix, networking.PathTypeImplementationSpecific}
    54  			path.PathType = &pathTypes[c.Rand.Intn(len(pathTypes))]
    55  		},
    56  		func(p *networking.ServiceBackendPort, c fuzz.Continue) {
    57  			c.FuzzNoCustom(p)
    58  			// clear one of the fields
    59  			if c.RandBool() {
    60  				p.Name = ""
    61  				if p.Number == 0 {
    62  					p.Number = 1
    63  				}
    64  			} else {
    65  				p.Number = 0
    66  				if p.Name == "" {
    67  					p.Name = "portname"
    68  				}
    69  			}
    70  		},
    71  		func(p *networking.IngressClass, c fuzz.Continue) {
    72  			c.FuzzNoCustom(p) // fuzz self without calling this function again
    73  			// default Parameters to Cluster
    74  			if p.Spec.Parameters == nil || p.Spec.Parameters.Scope == nil {
    75  				p.Spec.Parameters = &networking.IngressClassParametersReference{
    76  					Scope: utilpointer.String(networking.IngressClassParametersReferenceScopeCluster),
    77  				}
    78  			}
    79  		},
    80  		func(obj *networking.IPAddress, c fuzz.Continue) {
    81  			c.FuzzNoCustom(obj) // fuzz self without calling this function again
    82  			// length in bytes of the IP Family: IPv4: 4 bytes IPv6: 16 bytes
    83  			boolean := []bool{false, true}
    84  			is6 := boolean[c.Rand.Intn(2)]
    85  			ip := generateRandomIP(is6, c)
    86  			obj.Name = ip
    87  		},
    88  		func(obj *networking.ServiceCIDR, c fuzz.Continue) {
    89  			c.FuzzNoCustom(obj) // fuzz self without calling this function again
    90  			boolean := []bool{false, true}
    91  
    92  			is6 := boolean[c.Rand.Intn(2)]
    93  			primary := generateRandomCIDR(is6, c)
    94  			obj.Spec.CIDRs = []string{primary}
    95  
    96  			if boolean[c.Rand.Intn(2)] {
    97  				obj.Spec.CIDRs = append(obj.Spec.CIDRs, generateRandomCIDR(!is6, c))
    98  			}
    99  		},
   100  	}
   101  }
   102  
   103  func generateRandomIP(is6 bool, c fuzz.Continue) string {
   104  	n := 4
   105  	if is6 {
   106  		n = 16
   107  	}
   108  	bytes := make([]byte, n)
   109  	for i := 0; i < n; i++ {
   110  		bytes[i] = uint8(c.Rand.Intn(255))
   111  	}
   112  
   113  	ip, ok := netip.AddrFromSlice(bytes)
   114  	if ok {
   115  		return ip.String()
   116  	}
   117  	// this should not happen
   118  	panic(fmt.Sprintf("invalid IP %v", bytes))
   119  }
   120  
   121  func generateRandomCIDR(is6 bool, c fuzz.Continue) string {
   122  	ip, err := netip.ParseAddr(generateRandomIP(is6, c))
   123  	if err != nil {
   124  		// generateRandomIP already panics if returns a not valid ip
   125  		panic(err)
   126  	}
   127  
   128  	n := 32
   129  	if is6 {
   130  		n = 128
   131  	}
   132  
   133  	bits := c.Rand.Intn(n)
   134  	prefix := netip.PrefixFrom(ip, bits)
   135  	return prefix.Masked().String()
   136  }