github.com/cilium/cilium@v1.16.2/pkg/policy/api/cidr_test.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package api 5 6 import ( 7 "regexp" 8 "testing" 9 10 "github.com/stretchr/testify/require" 11 12 "github.com/cilium/cilium/pkg/labels" 13 "github.com/cilium/cilium/pkg/option" 14 ) 15 16 func TestGetAsEndpointSelectors(t *testing.T) { 17 world := labels.ParseLabelArray("reserved:world") 18 19 labelWorld := labels.ParseSelectLabel("reserved:world") 20 esWorld := NewESFromLabels(labelWorld) 21 22 labelWorldIPv4 := labels.ParseSelectLabel("reserved:world-ipv4") 23 esWorldIPv4 := NewESFromLabels(labelWorldIPv4) 24 25 labelWorldIPv6 := labels.ParseSelectLabel("reserved:world-ipv6") 26 esWorldIPv6 := NewESFromLabels(labelWorldIPv6) 27 28 labelAllV4, err := labels.IPStringToLabel("0.0.0.0/0") 29 require.Nil(t, err) 30 v4World := NewESFromLabels(labelAllV4) 31 32 labelAllV6, err := labels.IPStringToLabel("::/0") 33 require.Nil(t, err) 34 v6World := NewESFromLabels(labelAllV6) 35 36 labelOtherCIDR, err := labels.IPStringToLabel("192.168.128.0/24") 37 require.Nil(t, err) 38 esOtherCIDR := NewESFromLabels(labelOtherCIDR) 39 40 tt := []struct { 41 name string 42 cidrs CIDRSlice 43 expectedSelectors EndpointSelectorSlice 44 matchesWorld, 45 enableIPv4, enableIPv6 bool 46 }{ 47 { 48 name: "ipv4 dualstack", 49 cidrs: CIDRSlice{ 50 "0.0.0.0/0", 51 }, 52 expectedSelectors: EndpointSelectorSlice{ 53 v4World, 54 esWorldIPv4, 55 }, 56 matchesWorld: false, 57 enableIPv4: true, 58 enableIPv6: true, 59 }, 60 { 61 name: "ipv6 dualstack", 62 cidrs: CIDRSlice{ 63 "::/0", 64 }, 65 expectedSelectors: EndpointSelectorSlice{ 66 v6World, 67 esWorldIPv6, 68 }, 69 matchesWorld: false, 70 enableIPv4: true, 71 enableIPv6: true, 72 }, 73 { 74 name: "ipv4 and ipv6 dualstack", 75 cidrs: CIDRSlice{ 76 "0.0.0.0/0", 77 "::/0", 78 "192.168.128.10/24", 79 }, 80 expectedSelectors: EndpointSelectorSlice{ 81 v4World, 82 v6World, 83 esOtherCIDR, 84 esWorld, 85 esWorldIPv4, 86 esWorldIPv6, 87 }, 88 matchesWorld: true, 89 enableIPv4: true, 90 enableIPv6: true, 91 }, 92 { 93 name: "ipv4 in ipv4 only", 94 cidrs: CIDRSlice{ 95 "0.0.0.0/0", 96 }, 97 expectedSelectors: EndpointSelectorSlice{ 98 v4World, 99 esWorld, 100 }, 101 matchesWorld: true, 102 enableIPv4: true, 103 enableIPv6: false, 104 }, 105 { 106 name: "ipv6 in ipv4 only", 107 cidrs: CIDRSlice{ 108 "::/0", 109 }, 110 expectedSelectors: EndpointSelectorSlice{ 111 v6World, 112 }, 113 matchesWorld: false, 114 enableIPv4: true, 115 enableIPv6: false, 116 }, 117 { 118 name: "ipv4 in ipv6 only", 119 cidrs: CIDRSlice{ 120 "0.0.0.0/0", 121 }, 122 expectedSelectors: EndpointSelectorSlice{ 123 v4World, 124 }, 125 matchesWorld: false, 126 enableIPv4: false, 127 enableIPv6: true, 128 }, 129 { 130 name: "ipv6 in ipv6 only", 131 cidrs: CIDRSlice{ 132 "::/0", 133 }, 134 expectedSelectors: EndpointSelectorSlice{ 135 v6World, 136 esWorld, 137 }, 138 matchesWorld: true, 139 enableIPv4: false, 140 enableIPv6: true, 141 }, 142 } 143 144 for _, test := range tt { 145 t.Logf("running test %s:", test.name) 146 option.Config.EnableIPv6 = test.enableIPv6 147 option.Config.EnableIPv4 = test.enableIPv4 148 result := test.cidrs.GetAsEndpointSelectors() 149 require.Equal(t, test.matchesWorld, result.Matches(world)) 150 require.EqualValues(t, test.expectedSelectors, result) 151 } 152 option.Config.EnableIPv4 = true 153 option.Config.EnableIPv6 = true 154 } 155 156 const CIDRRegex = `^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/([0-9]|[1-2][0-9]|3[0-2])$|^s*((([0-9A-Fa-f]{1,4}:){7}(:|([0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4}:){6}:([0-9A-Fa-f]{1,4})?)|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){0,1}):([0-9A-Fa-f]{1,4})?))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){0,2}):([0-9A-Fa-f]{1,4})?))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){0,3}):([0-9A-Fa-f]{1,4})?))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){0,4}):([0-9A-Fa-f]{1,4})?))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){0,5}):([0-9A-Fa-f]{1,4})?))|(:(:|((:[0-9A-Fa-f]{1,4}){1,7}))))(%.+)?s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$` 157 158 func TestCIDRRegex(t *testing.T) { 159 reg := regexp.MustCompile(CIDRRegex) 160 161 goodCIDRs := []string{ 162 "192.0.2.3/32", 163 "192.0.2.0/24", 164 "0.0.0.0/0", 165 "::/0", 166 "::cafe/128", 167 "::f00d:cafe/128", 168 "0:0:0:0:0:0:0:cafe/128", 169 "cafe:cafe:cafe:cafe:cafe:cafe:cafe:cafe/128", 170 "bad:f00d:cafe:0:0:0:0:add/64", 171 "bad:f00d:cafe::bad/64", 172 "f00d::/64", 173 "f00d::0:0/120", 174 "f00d:cafe::1:2/120", 175 } 176 177 continueTest: 178 for _, input := range goodCIDRs { 179 if matched := reg.MatchString(input); matched { 180 continue continueTest 181 } 182 // The below is always false, valid CIDR prefixes should 183 // always skip this by continuing in the above loop. 184 require.Equal(t, "failed to match CIDR.OneOf[*].Pattern", input) 185 } 186 187 badCIDRs := []string{ 188 "192.0.2.3", 189 "192.0.2.3/", 190 "abcdef", 191 "0.0.0.0/0/0", 192 "::", 193 ":", 194 ":/", 195 "0:0", 196 "::cafe/128/12", 197 "abc:def", 198 "abc:def/64", 199 "f00d::/", 200 "f00d::0:0", 201 "bad.f00d.cafe.0.0.0.0.add/20", 202 "::192.0.2.3/128", 203 "::ffff:192.0.2.3/128", 204 "abcd:192.0.2.3/128", 205 ":abcd:192.0.2.3/128", 206 "abcd::192.0.2.3/128", 207 ":abcd::192.0.2.3/128", 208 "bad::f00d::cafe/1", 209 ":bad::f00d::cafe/1", 210 "::bad::f00d::cafe/1", 211 "::bad::food::cafe/1", 212 } 213 214 for _, input := range badCIDRs { 215 if matched := reg.MatchString(input); matched { 216 // The below is always false, invalid CIDR 217 // prefixes are not supposed to match the regex. 218 require.Equal(t, "unexpectedly matched CIDR.OneOf[*].Pattern", input) 219 } 220 } 221 }