@@ -20,7 +20,6 @@ import (
2020 "os"
2121 "os/exec"
2222 "path/filepath"
23- "strings"
2423
2524 . "github.com/onsi/ginkgo/v2"
2625 . "github.com/onsi/gomega"
@@ -31,6 +30,8 @@ import (
3130 "github.com/containernetworking/plugins/pkg/testutils"
3231)
3332
33+ const nsCount = 3
34+
3435// The integration tests expect the "firewall" binary to be present in $PATH.
3536// To run test, e.g, : go test -exec "sudo -E PATH=$(pwd):/opt/cni/bin:$PATH" -v -ginkgo.v
3637var _ = Describe ("firewall integration tests (ingressPolicy: same-bridge)" , func () {
@@ -39,24 +40,23 @@ var _ = Describe("firewall integration tests (ingressPolicy: same-bridge)", func
3940 // ns2: bar (10.88.4.0/24)
4041 //
4142 // ns0@foo can talk to ns1@foo, but cannot talk to ns2@bar
42- const nsCount = 3
43+
4344 var (
4445 configListFoo * libcni.NetworkConfigList // "foo", 10.88.3.0/24
4546 configListBar * libcni.NetworkConfigList // "bar", 10.88.4.0/24
4647 cniConf * libcni.CNIConfig
4748 namespaces [nsCount ]ns.NetNS
49+ results [nsCount ]* types100.Result
4850 )
4951
50- BeforeEach (func () {
51- var err error
52- rawConfigFoo := `
53- {
52+ createNetworkConfig := func (name string , subnet string , gateway string , ingressPolicy string ) string {
53+ return fmt .Sprintf (`{
5454 "cniVersion": "1.0.0",
55- "name": "foo ",
55+ "name": "%s ",
5656 "plugins": [
5757 {
5858 "type": "bridge",
59- "bridge": "foo ",
59+ "bridge": "%s ",
6060 "isGateway": true,
6161 "ipMasq": true,
6262 "hairpinMode": true,
@@ -70,8 +70,8 @@ var _ = Describe("firewall integration tests (ingressPolicy: same-bridge)", func
7070 "ranges": [
7171 [
7272 {
73- "subnet": "10.88.3.0/24 ",
74- "gateway": "10.88.3.1 "
73+ "subnet": "%s ",
74+ "gateway": "%s "
7575 }
7676 ]
7777 ]
@@ -80,19 +80,14 @@ var _ = Describe("firewall integration tests (ingressPolicy: same-bridge)", func
8080 {
8181 "type": "firewall",
8282 "backend": "iptables",
83- "ingressPolicy": "same-bridge "
83+ "ingressPolicy": "%s "
8484 }
8585 ]
86- }
87- `
88- configListFoo , err = libcni .ConfListFromBytes ([]byte (rawConfigFoo ))
89- Expect (err ).NotTo (HaveOccurred ())
90-
91- rawConfigBar := strings .ReplaceAll (rawConfigFoo , "foo" , "bar" )
92- rawConfigBar = strings .ReplaceAll (rawConfigBar , "10.88.3." , "10.88.4." )
86+ }` , name , name , subnet , gateway , ingressPolicy )
87+ }
9388
94- configListBar , err = libcni . ConfListFromBytes ([] byte ( rawConfigBar ))
95- Expect ( err ). NotTo ( HaveOccurred ())
89+ BeforeEach ( func () {
90+ var err error
9691
9792 // turn PATH in to CNI_PATH.
9893 _ , err = exec .LookPath ("firewall" )
@@ -116,89 +111,129 @@ var _ = Describe("firewall integration tests (ingressPolicy: same-bridge)", func
116111 }
117112 })
118113
119- Describe ("Testing with network foo and bar" , func () {
120- It ("should isolate foo from bar" , func () {
121- var results [nsCount ]* types100.Result
122- for i := 0 ; i < nsCount ; i ++ {
123- runtimeConfig := libcni.RuntimeConf {
124- ContainerID : fmt .Sprintf ("test-cni-firewall-%d" , i ),
125- NetNS : namespaces [i ].Path (),
126- IfName : "eth0" ,
127- }
128-
129- configList := configListFoo
130- switch i {
131- case 0 , 1 :
132- // leave foo
133- default :
134- configList = configListBar
135- }
136-
137- // Clean up garbages produced during past failed executions
138- _ = cniConf .DelNetworkList (context .TODO (), configList , & runtimeConfig )
139-
140- // Make delete idempotent, so we can clean up on failure
141- netDeleted := false
142- deleteNetwork := func () error {
143- if netDeleted {
144- return nil
145- }
146- netDeleted = true
147- return cniConf .DelNetworkList (context .TODO (), configList , & runtimeConfig )
148- }
149- // Create the network
150- res , err := cniConf .AddNetworkList (context .TODO (), configList , & runtimeConfig )
151- Expect (err ).NotTo (HaveOccurred ())
152- // nolint: errcheck
153- defer deleteNetwork ()
154-
155- results [i ], err = types100 .NewResultFromResult (res )
156- Expect (err ).NotTo (HaveOccurred ())
157- fmt .Fprintf (GinkgoWriter , "results[%d]: %+v\n " , i , results [i ])
158- }
159- ping := func (src , dst int ) error {
160- return namespaces [src ].Do (func (ns.NetNS ) error {
161- defer GinkgoRecover ()
162- saddr := results [src ].IPs [0 ].Address .IP .String ()
163- daddr := results [dst ].IPs [0 ].Address .IP .String ()
164- srcNetName := results [src ].Interfaces [0 ].Name
165- dstNetName := results [dst ].Interfaces [0 ].Name
166-
167- fmt .Fprintf (GinkgoWriter , "ping %s (ns%d@%s) -> %s (ns%d@%s)..." ,
168- saddr , src , srcNetName , daddr , dst , dstNetName )
169- timeoutSec := 1
170- if err := testutils .Ping (saddr , daddr , timeoutSec ); err != nil {
171- fmt .Fprintln (GinkgoWriter , "unpingable" )
172- return err
173- }
174- fmt .Fprintln (GinkgoWriter , "pingable" )
175- return nil
176- })
177- }
178-
179- // ns0@foo can ping to ns1@foo
180- err := ping (0 , 1 )
114+ Describe ("Testing with ingress-policy 'same-bridge" , func () {
115+ BeforeEach (func () {
116+ var err error
117+ configListFoo , err = libcni .ConfListFromBytes ([]byte (
118+ createNetworkConfig ("foo" , "10.88.3.0/24" , "10.88.3.1" , "same-bridge" )))
181119 Expect (err ).NotTo (HaveOccurred ())
182120
183- // ns1@foo can ping to ns0@foo
184- err = ping ( 1 , 0 )
121+ configListBar , err = libcni . ConfListFromBytes ([] byte (
122+ createNetworkConfig ( "bar" , "10.88.4.0/24" , "10.88.4.1" , "same-bridge" )) )
185123 Expect (err ).NotTo (HaveOccurred ())
186124
187- // ns0@foo cannot ping to ns2@bar
188- err = ping (0 , 2 )
189- Expect (err ).To (HaveOccurred ())
125+ results = setupNetworks (cniConf , namespaces , configListFoo , configListBar )
126+ })
127+
128+ Context ("when testing connectivity" , func () {
129+ It ("should allow communication within foo network" , func () {
130+ err := ping (namespaces , results , 0 , 1 )
131+ Expect (err ).To (Succeed ())
132+ err = ping (namespaces , results , 1 , 0 )
133+ Expect (err ).To (Succeed ())
134+ })
135+
136+ It ("should prevent communication between foo and bar networks" , func () {
137+ err := ping (namespaces , results , 0 , 2 )
138+ Expect (err ).To (HaveOccurred ())
139+ err = ping (namespaces , results , 1 , 2 )
140+ Expect (err ).To (HaveOccurred ())
141+ err = ping (namespaces , results , 2 , 0 )
142+ Expect (err ).To (HaveOccurred ())
143+ err = ping (namespaces , results , 2 , 1 )
144+ Expect (err ).To (HaveOccurred ())
145+ })
146+ })
147+ })
190148
191- // ns1@foo cannot ping to ns2@bar
192- err = ping (1 , 2 )
193- Expect (err ).To (HaveOccurred ())
149+ Describe ("Testing with ingress-policy 'isolated" , func () {
150+ BeforeEach (func () {
151+ var err error
152+ configListFoo , err = libcni .ConfListFromBytes ([]byte (
153+ createNetworkConfig ("foo" , "10.88.3.0/24" , "10.88.3.1" , "isolated" )))
154+ Expect (err ).NotTo (HaveOccurred ())
194155
195- // ns2@bar cannot ping to ns0@foo
196- err = ping ( 2 , 0 )
197- Expect (err ).To (HaveOccurred ())
156+ configListBar , err = libcni . ConfListFromBytes ([] byte (
157+ createNetworkConfig ( "bar" , "10.88.4.0/24" , "10.88.4.1" , "isolated" )) )
158+ Expect (err ).NotTo (HaveOccurred ())
198159
199- // ns2@bar cannot ping to ns1@foo
200- err = ping (2 , 1 )
201- Expect (err ).To (HaveOccurred ())
160+ results = setupNetworks (cniConf , namespaces , configListFoo , configListBar )
161+ })
162+
163+ Context ("when testing connectivity" , func () {
164+ It ("should prevent communication within foo network" , func () {
165+ err := ping (namespaces , results , 0 , 1 )
166+ Expect (err ).To (HaveOccurred ())
167+ err = ping (namespaces , results , 1 , 0 )
168+ Expect (err ).To (HaveOccurred ())
169+ })
170+
171+ It ("should prevent communication between foo and bar networks" , func () {
172+ err := ping (namespaces , results , 0 , 2 )
173+ Expect (err ).To (HaveOccurred ())
174+ err = ping (namespaces , results , 1 , 2 )
175+ Expect (err ).To (HaveOccurred ())
176+ err = ping (namespaces , results , 2 , 0 )
177+ Expect (err ).To (HaveOccurred ())
178+ err = ping (namespaces , results , 2 , 1 )
179+ Expect (err ).To (HaveOccurred ())
180+ })
202181 })
203182 })
204183})
184+
185+ func setupNetworks (cniConf * libcni.CNIConfig , namespaces [nsCount ]ns.NetNS ,
186+ configListFoo , configListBar * libcni.NetworkConfigList ,
187+ ) [nsCount ]* types100.Result {
188+ var results [nsCount ]* types100.Result
189+
190+ for i := 0 ; i < nsCount ; i ++ {
191+ runtimeConfig := libcni.RuntimeConf {
192+ ContainerID : fmt .Sprintf ("test-cni-firewall-%d" , i ),
193+ NetNS : namespaces [i ].Path (),
194+ IfName : "eth0" ,
195+ }
196+
197+ configList := configListFoo
198+ if i >= 2 {
199+ configList = configListBar
200+ }
201+
202+ // Cleanup any existing network
203+ _ = cniConf .DelNetworkList (context .TODO (), configList , & runtimeConfig )
204+
205+ // Create network
206+ res , err := cniConf .AddNetworkList (context .TODO (), configList , & runtimeConfig )
207+ Expect (err ).NotTo (HaveOccurred ())
208+
209+ // Setup cleanup
210+ DeferCleanup (func () {
211+ _ = cniConf .DelNetworkList (context .TODO (), configList , & runtimeConfig )
212+ })
213+
214+ results [i ], err = types100 .NewResultFromResult (res )
215+ Expect (err ).NotTo (HaveOccurred ())
216+ }
217+
218+ return results
219+ }
220+
221+ func ping (namespaces [nsCount ]ns.NetNS , results [nsCount ]* types100.Result , src , dst int ) error {
222+ return namespaces [src ].Do (func (ns.NetNS ) error {
223+ defer GinkgoRecover ()
224+ saddr := results [src ].IPs [0 ].Address .IP .String ()
225+ daddr := results [dst ].IPs [0 ].Address .IP .String ()
226+ srcNetName := results [src ].Interfaces [0 ].Name
227+ dstNetName := results [dst ].Interfaces [0 ].Name
228+
229+ fmt .Fprintf (GinkgoWriter , "ping %s (ns%d@%s) -> %s (ns%d@%s)..." ,
230+ saddr , src , srcNetName , daddr , dst , dstNetName )
231+ timeoutSec := 1
232+ if err := testutils .Ping (saddr , daddr , timeoutSec ); err != nil {
233+ fmt .Fprintln (GinkgoWriter , "unpingable" )
234+ return err
235+ }
236+ fmt .Fprintln (GinkgoWriter , "pingable" )
237+ return nil
238+ })
239+ }
0 commit comments