k8s.io/kubernetes@v1.29.3/pkg/util/iptables/testing/fake_test.go (about) 1 /* 2 Copyright 2022 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 testing 18 19 import ( 20 "bytes" 21 "strings" 22 "testing" 23 24 "github.com/lithammer/dedent" 25 26 "k8s.io/kubernetes/pkg/util/iptables" 27 ) 28 29 func TestFakeIPTables(t *testing.T) { 30 fake := NewFake() 31 buf := bytes.NewBuffer(nil) 32 33 err := fake.SaveInto("", buf) 34 if err != nil { 35 t.Fatalf("unexpected error from SaveInto: %v", err) 36 } 37 expected := dedent.Dedent(strings.Trim(` 38 *nat 39 :PREROUTING - [0:0] 40 :INPUT - [0:0] 41 :OUTPUT - [0:0] 42 :POSTROUTING - [0:0] 43 COMMIT 44 *filter 45 :INPUT - [0:0] 46 :FORWARD - [0:0] 47 :OUTPUT - [0:0] 48 COMMIT 49 *mangle 50 COMMIT 51 `, "\n")) 52 if buf.String() != expected { 53 t.Fatalf("bad initial dump. expected:\n%s\n\ngot:\n%s\n", expected, buf.Bytes()) 54 } 55 56 // EnsureChain 57 existed, err := fake.EnsureChain(iptables.Table("blah"), iptables.Chain("KUBE-TEST")) 58 if err == nil { 59 t.Errorf("did not get expected error creating chain in non-existent table") 60 } else if existed { 61 t.Errorf("wrong return value from EnsureChain with non-existent table") 62 } 63 existed, err = fake.EnsureChain(iptables.TableNAT, iptables.Chain("KUBE-TEST")) 64 if err != nil { 65 t.Errorf("unexpected error creating chain: %v", err) 66 } else if existed { 67 t.Errorf("wrong return value from EnsureChain with non-existent chain") 68 } 69 existed, err = fake.EnsureChain(iptables.TableNAT, iptables.Chain("KUBE-TEST")) 70 if err != nil { 71 t.Errorf("unexpected error creating chain: %v", err) 72 } else if !existed { 73 t.Errorf("wrong return value from EnsureChain with existing chain") 74 } 75 76 // ChainExists 77 exists, err := fake.ChainExists(iptables.TableNAT, iptables.Chain("KUBE-TEST")) 78 if err != nil { 79 t.Errorf("unexpected error checking chain: %v", err) 80 } else if !exists { 81 t.Errorf("wrong return value from ChainExists with existing chain") 82 } 83 exists, err = fake.ChainExists(iptables.TableNAT, iptables.Chain("KUBE-TEST-NOT")) 84 if err != nil { 85 t.Errorf("unexpected error checking chain: %v", err) 86 } else if exists { 87 t.Errorf("wrong return value from ChainExists with non-existent chain") 88 } 89 90 // EnsureRule 91 existed, err = fake.EnsureRule(iptables.Append, iptables.Table("blah"), iptables.Chain("KUBE-TEST"), "-j", "ACCEPT") 92 if err == nil { 93 t.Errorf("did not get expected error creating rule in non-existent table") 94 } else if existed { 95 t.Errorf("wrong return value from EnsureRule with non-existent table") 96 } 97 existed, err = fake.EnsureRule(iptables.Append, iptables.TableNAT, iptables.Chain("KUBE-TEST-NOT"), "-j", "ACCEPT") 98 if err == nil { 99 t.Errorf("did not get expected error creating rule in non-existent chain") 100 } else if existed { 101 t.Errorf("wrong return value from EnsureRule with non-existent chain") 102 } 103 existed, err = fake.EnsureRule(iptables.Append, iptables.TableNAT, iptables.Chain("KUBE-TEST"), "-j", "ACCEPT") 104 if err != nil { 105 t.Errorf("unexpected error creating rule: %v", err) 106 } else if existed { 107 t.Errorf("wrong return value from EnsureRule with non-existent rule") 108 } 109 existed, err = fake.EnsureRule(iptables.Prepend, iptables.TableNAT, iptables.Chain("KUBE-TEST"), "-j", "DROP") 110 if err != nil { 111 t.Errorf("unexpected error creating rule: %v", err) 112 } else if existed { 113 t.Errorf("wrong return value from EnsureRule with non-existent rule") 114 } 115 existed, err = fake.EnsureRule(iptables.Append, iptables.TableNAT, iptables.Chain("KUBE-TEST"), "-j", "DROP") 116 if err != nil { 117 t.Errorf("unexpected error creating rule: %v", err) 118 } else if !existed { 119 t.Errorf("wrong return value from EnsureRule with already-existing rule") 120 } 121 122 // Sanity-check... 123 buf.Reset() 124 err = fake.SaveInto("", buf) 125 if err != nil { 126 t.Fatalf("unexpected error from SaveInto: %v", err) 127 } 128 expected = dedent.Dedent(strings.Trim(` 129 *nat 130 :PREROUTING - [0:0] 131 :INPUT - [0:0] 132 :OUTPUT - [0:0] 133 :POSTROUTING - [0:0] 134 :KUBE-TEST - [0:0] 135 -A KUBE-TEST -j DROP 136 -A KUBE-TEST -j ACCEPT 137 COMMIT 138 *filter 139 :INPUT - [0:0] 140 :FORWARD - [0:0] 141 :OUTPUT - [0:0] 142 COMMIT 143 *mangle 144 COMMIT 145 `, "\n")) 146 if buf.String() != expected { 147 t.Fatalf("bad sanity-check dump. expected:\n%s\n\ngot:\n%s\n", expected, buf.Bytes()) 148 } 149 150 // DeleteRule 151 err = fake.DeleteRule(iptables.Table("blah"), iptables.Chain("KUBE-TEST"), "-j", "DROP") 152 if err == nil { 153 t.Errorf("did not get expected error deleting rule in non-existent table") 154 } 155 err = fake.DeleteRule(iptables.TableNAT, iptables.Chain("KUBE-TEST-NOT"), "-j", "DROP") 156 if err == nil { 157 t.Errorf("did not get expected error deleting rule in non-existent chain") 158 } 159 err = fake.DeleteRule(iptables.TableNAT, iptables.Chain("KUBE-TEST"), "-j", "DROPLET") 160 if err != nil { 161 t.Errorf("unexpected error deleting non-existent rule: %v", err) 162 } 163 err = fake.DeleteRule(iptables.TableNAT, iptables.Chain("KUBE-TEST"), "-j", "DROP") 164 if err != nil { 165 t.Errorf("unexpected error deleting rule: %v", err) 166 } 167 168 // Restore 169 rules := dedent.Dedent(strings.Trim(` 170 *nat 171 :KUBE-RESTORED - [0:0] 172 :KUBE-MISC-CHAIN - [0:0] 173 :KUBE-MISC-TWO - [0:0] 174 :KUBE-EMPTY - [0:0] 175 -A KUBE-RESTORED -m comment --comment "restored chain" -j ACCEPT 176 -A KUBE-MISC-CHAIN -s 1.2.3.4 -j KUBE-MISC-TWO 177 -A KUBE-MISC-CHAIN -d 5.6.7.8 -j MASQUERADE 178 -A KUBE-MISC-TWO -j ACCEPT 179 COMMIT 180 `, "\n")) 181 err = fake.Restore(iptables.TableNAT, []byte(rules), iptables.NoFlushTables, iptables.NoRestoreCounters) 182 if err != nil { 183 t.Fatalf("unexpected error from Restore: %v", err) 184 } 185 186 // We used NoFlushTables, so this should leave KUBE-TEST unchanged 187 buf.Reset() 188 err = fake.SaveInto("", buf) 189 if err != nil { 190 t.Fatalf("unexpected error from SaveInto: %v", err) 191 } 192 expected = dedent.Dedent(strings.Trim(` 193 *nat 194 :PREROUTING - [0:0] 195 :INPUT - [0:0] 196 :OUTPUT - [0:0] 197 :POSTROUTING - [0:0] 198 :KUBE-TEST - [0:0] 199 :KUBE-RESTORED - [0:0] 200 :KUBE-MISC-CHAIN - [0:0] 201 :KUBE-MISC-TWO - [0:0] 202 :KUBE-EMPTY - [0:0] 203 -A KUBE-TEST -j ACCEPT 204 -A KUBE-RESTORED -m comment --comment "restored chain" -j ACCEPT 205 -A KUBE-MISC-CHAIN -s 1.2.3.4 -j KUBE-MISC-TWO 206 -A KUBE-MISC-CHAIN -d 5.6.7.8 -j MASQUERADE 207 -A KUBE-MISC-TWO -j ACCEPT 208 COMMIT 209 *filter 210 :INPUT - [0:0] 211 :FORWARD - [0:0] 212 :OUTPUT - [0:0] 213 COMMIT 214 *mangle 215 COMMIT 216 `, "\n")) 217 if buf.String() != expected { 218 t.Fatalf("bad post-restore dump. expected:\n%s\n\ngot:\n%s\n", expected, buf.Bytes()) 219 } 220 221 // Trying to use Restore to delete a chain that another chain jumps to will fail 222 rules = dedent.Dedent(strings.Trim(` 223 *nat 224 :KUBE-MISC-TWO - [0:0] 225 -X KUBE-MISC-TWO 226 COMMIT 227 `, "\n")) 228 err = fake.Restore(iptables.TableNAT, []byte(rules), iptables.NoFlushTables, iptables.RestoreCounters) 229 if err == nil || !strings.Contains(err.Error(), "referenced by existing rules") { 230 t.Fatalf("Expected 'referenced by existing rules' error from Restore, got %v", err) 231 } 232 233 // Trying to use Restore to add a jump to a non-existent chain will fail 234 rules = dedent.Dedent(strings.Trim(` 235 *nat 236 :KUBE-MISC-TWO - [0:0] 237 -A KUBE-MISC-TWO -j KUBE-MISC-THREE 238 COMMIT 239 `, "\n")) 240 err = fake.Restore(iptables.TableNAT, []byte(rules), iptables.NoFlushTables, iptables.RestoreCounters) 241 if err == nil || !strings.Contains(err.Error(), "non-existent chain") { 242 t.Fatalf("Expected 'non-existent chain' error from Restore, got %v", err) 243 } 244 245 // more Restore; empty out one chain and delete another, but also update its counters 246 rules = dedent.Dedent(strings.Trim(` 247 *nat 248 :KUBE-RESTORED - [0:0] 249 :KUBE-TEST - [99:9999] 250 -X KUBE-RESTORED 251 COMMIT 252 `, "\n")) 253 err = fake.Restore(iptables.TableNAT, []byte(rules), iptables.NoFlushTables, iptables.RestoreCounters) 254 if err != nil { 255 t.Fatalf("unexpected error from Restore: %v", err) 256 } 257 258 buf.Reset() 259 err = fake.SaveInto("", buf) 260 if err != nil { 261 t.Fatalf("unexpected error from SaveInto: %v", err) 262 } 263 expected = dedent.Dedent(strings.Trim(` 264 *nat 265 :PREROUTING - [0:0] 266 :INPUT - [0:0] 267 :OUTPUT - [0:0] 268 :POSTROUTING - [0:0] 269 :KUBE-TEST - [99:9999] 270 :KUBE-MISC-CHAIN - [0:0] 271 :KUBE-MISC-TWO - [0:0] 272 :KUBE-EMPTY - [0:0] 273 -A KUBE-MISC-CHAIN -s 1.2.3.4 -j KUBE-MISC-TWO 274 -A KUBE-MISC-CHAIN -d 5.6.7.8 -j MASQUERADE 275 -A KUBE-MISC-TWO -j ACCEPT 276 COMMIT 277 *filter 278 :INPUT - [0:0] 279 :FORWARD - [0:0] 280 :OUTPUT - [0:0] 281 COMMIT 282 *mangle 283 COMMIT 284 `, "\n")) 285 if buf.String() != expected { 286 t.Fatalf("bad post-second-restore dump. expected:\n%s\n\ngot:\n%s\n", expected, buf.Bytes()) 287 } 288 289 // RestoreAll, FlushTables 290 rules = dedent.Dedent(strings.Trim(` 291 *filter 292 :INPUT - [0:0] 293 :FORWARD - [0:0] 294 :OUTPUT - [0:0] 295 :KUBE-TEST - [0:0] 296 -A KUBE-TEST -m comment --comment "filter table KUBE-TEST" -j ACCEPT 297 COMMIT 298 *nat 299 :PREROUTING - [0:0] 300 :INPUT - [0:0] 301 :OUTPUT - [0:0] 302 :POSTROUTING - [0:0] 303 :KUBE-TEST - [88:8888] 304 :KUBE-NEW-CHAIN - [0:0] 305 -A KUBE-NEW-CHAIN -d 172.30.0.1 -j DNAT --to-destination 10.0.0.1 306 -A KUBE-NEW-CHAIN -d 172.30.0.2 -j DNAT --to-destination 10.0.0.2 307 -A KUBE-NEW-CHAIN -d 172.30.0.3 -j DNAT --to-destination 10.0.0.3 308 COMMIT 309 `, "\n")) 310 err = fake.RestoreAll([]byte(rules), iptables.FlushTables, iptables.NoRestoreCounters) 311 if err != nil { 312 t.Fatalf("unexpected error from RestoreAll: %v", err) 313 } 314 315 buf.Reset() 316 err = fake.SaveInto("", buf) 317 if err != nil { 318 t.Fatalf("unexpected error from SaveInto: %v", err) 319 } 320 expected = dedent.Dedent(strings.Trim(` 321 *nat 322 :PREROUTING - [0:0] 323 :INPUT - [0:0] 324 :OUTPUT - [0:0] 325 :POSTROUTING - [0:0] 326 :KUBE-TEST - [88:8888] 327 :KUBE-NEW-CHAIN - [0:0] 328 -A KUBE-NEW-CHAIN -d 172.30.0.1 -j DNAT --to-destination 10.0.0.1 329 -A KUBE-NEW-CHAIN -d 172.30.0.2 -j DNAT --to-destination 10.0.0.2 330 -A KUBE-NEW-CHAIN -d 172.30.0.3 -j DNAT --to-destination 10.0.0.3 331 COMMIT 332 *filter 333 :INPUT - [0:0] 334 :FORWARD - [0:0] 335 :OUTPUT - [0:0] 336 :KUBE-TEST - [0:0] 337 -A KUBE-TEST -m comment --comment "filter table KUBE-TEST" -j ACCEPT 338 COMMIT 339 *mangle 340 COMMIT 341 `, "\n")) 342 if buf.String() != expected { 343 t.Fatalf("bad post-restore-all dump. expected:\n%s\n\ngot:\n%s\n", expected, buf.Bytes()) 344 } 345 }