@@ -5,21 +5,23 @@ import (
55 "context"
66 "encoding/json"
77 "fmt"
8+ "maps"
89 "net"
10+ "net/netip"
911 "os/exec"
10- "regexp "
12+ "slices "
1113 "strconv"
1214 "testing"
1315
1416 "github.com/docker/docker/internal/nlwrap"
1517 "github.com/docker/docker/internal/testutils/netnsutils"
1618 "github.com/docker/docker/internal/testutils/storeutils"
1719 "github.com/docker/docker/libnetwork/driverapi"
20+ "github.com/docker/docker/libnetwork/drivers/bridge/internal/firewaller"
1821 "github.com/docker/docker/libnetwork/internal/netiputil"
1922 "github.com/docker/docker/libnetwork/ipamapi"
2023 "github.com/docker/docker/libnetwork/ipams/defaultipam"
2124 "github.com/docker/docker/libnetwork/ipamutils"
22- "github.com/docker/docker/libnetwork/iptables"
2325 "github.com/docker/docker/libnetwork/netlabel"
2426 "github.com/docker/docker/libnetwork/netutils"
2527 "github.com/docker/docker/libnetwork/options"
@@ -33,13 +35,6 @@ import (
3335 "gotest.tools/v3/icmd"
3436)
3537
36- const (
37- // FIXME(robmry) - remove these and make the tests work for non-iptables firewalls.
38- dockerChain = "DOCKER"
39- isolationChain1 = "DOCKER-ISOLATION-STAGE-1"
40- isolationChain2 = "DOCKER-ISOLATION-STAGE-2"
41- )
42-
4338func TestEndpointMarshalling (t * testing.T ) {
4439 ip1 , _ := types .ParseCIDR ("172.22.0.9/16" )
4540 ip2 , _ := types .ParseCIDR ("2001:db8::9" )
@@ -582,9 +577,22 @@ func TestCreateFail(t *testing.T) {
582577
583578func TestCreateMultipleNetworks (t * testing.T ) {
584579 defer netnsutils .SetupTestOSContext (t )()
580+ useStubFirewaller (t )
585581
586582 d := newDriver (storeutils .NewTempStore (t ))
587583
584+ checkFirewallerNetworks := func () {
585+ t .Helper ()
586+ fw := d .firewaller .(* firewaller.StubFirewaller )
587+ got := maps .Clone (fw .Networks )
588+ for _ , wantNw := range d .networks {
589+ _ , ok := got [wantNw .config .BridgeName ]
590+ assert .Check (t , ok , "Rules for bridge %s (nid:%s) have been deleted" , wantNw .config .BridgeName , wantNw .id )
591+ delete (got , wantNw .config .BridgeName )
592+ }
593+ assert .Check (t , is .Len (slices .Collect (maps .Keys (got )), 0 ), "Rules for bridges have not been deleted" )
594+ }
595+
588596 config := & configuration {
589597 EnableIPTables : true ,
590598 }
@@ -601,78 +609,48 @@ func TestCreateMultipleNetworks(t *testing.T) {
601609 if err := d .CreateNetwork (context .Background (), "1" , genericOption , nil , getIPv4Data (t ), nil ); err != nil {
602610 t .Fatalf ("Failed to create bridge: %v" , err )
603611 }
604-
605- verifyV4INCEntries (d .networks , t )
612+ checkFirewallerNetworks ()
606613
607614 config2 := & networkConfiguration {BridgeName : "net_test_2" , EnableIPv4 : true }
608615 genericOption [netlabel .GenericData ] = config2
609616 if err := d .CreateNetwork (context .Background (), "2" , genericOption , nil , getIPv4Data (t ), nil ); err != nil {
610617 t .Fatalf ("Failed to create bridge: %v" , err )
611618 }
612-
613- verifyV4INCEntries (d .networks , t )
619+ checkFirewallerNetworks ()
614620
615621 config3 := & networkConfiguration {BridgeName : "net_test_3" , EnableIPv4 : true }
616622 genericOption [netlabel .GenericData ] = config3
617623 if err := d .CreateNetwork (context .Background (), "3" , genericOption , nil , getIPv4Data (t ), nil ); err != nil {
618624 t .Fatalf ("Failed to create bridge: %v" , err )
619625 }
620-
621- verifyV4INCEntries (d .networks , t )
626+ checkFirewallerNetworks ()
622627
623628 config4 := & networkConfiguration {BridgeName : "net_test_4" , EnableIPv4 : true }
624629 genericOption [netlabel .GenericData ] = config4
625630 if err := d .CreateNetwork (context .Background (), "4" , genericOption , nil , getIPv4Data (t ), nil ); err != nil {
626631 t .Fatalf ("Failed to create bridge: %v" , err )
627632 }
628-
629- verifyV4INCEntries (d .networks , t )
633+ checkFirewallerNetworks ()
630634
631635 if err := d .DeleteNetwork ("1" ); err != nil {
632636 t .Log (err )
633637 }
634- verifyV4INCEntries ( d . networks , t )
638+ checkFirewallerNetworks ( )
635639
636640 if err := d .DeleteNetwork ("2" ); err != nil {
637641 t .Log (err )
638642 }
639- verifyV4INCEntries ( d . networks , t )
643+ checkFirewallerNetworks ( )
640644
641645 if err := d .DeleteNetwork ("3" ); err != nil {
642646 t .Log (err )
643647 }
644- verifyV4INCEntries ( d . networks , t )
648+ checkFirewallerNetworks ( )
645649
646650 if err := d .DeleteNetwork ("4" ); err != nil {
647651 t .Log (err )
648652 }
649- verifyV4INCEntries (d .networks , t )
650- }
651-
652- // Verify the network isolation rules are installed for each network
653- func verifyV4INCEntries (networks map [string ]* bridgeNetwork , t * testing.T ) {
654- iptable := iptables .GetIptable (iptables .IPv4 )
655- out1 , err := iptable .Raw ("-S" , isolationChain1 )
656- if err != nil {
657- t .Fatal (err )
658- }
659- out2 , err := iptable .Raw ("-S" , isolationChain2 )
660- if err != nil {
661- t .Fatal (err )
662- }
663-
664- for _ , n := range networks {
665- re := regexp .MustCompile (fmt .Sprintf ("-i %s ! -o %s -j %s" , n .config .BridgeName , n .config .BridgeName , isolationChain2 ))
666- matches := re .FindAllString (string (out1 [:]), - 1 )
667- if len (matches ) != 1 {
668- t .Fatalf ("Cannot find expected inter-network isolation rules in IP Tables for network %s:\n %s." , n .id , string (out1 [:]))
669- }
670- re = regexp .MustCompile (fmt .Sprintf ("-o %s -j DROP" , n .config .BridgeName ))
671- matches = re .FindAllString (string (out2 [:]), - 1 )
672- if len (matches ) != 1 {
673- t .Fatalf ("Cannot find expected inter-network isolation rules in IP Tables for network %s:\n %s." , n .id , string (out2 [:]))
674- }
675- }
653+ checkFirewallerNetworks ()
676654}
677655
678656type testInterface struct {
@@ -812,6 +790,8 @@ func TestQueryEndpointInfoHairpin(t *testing.T) {
812790
813791func testQueryEndpointInfo (t * testing.T , ulPxyEnabled bool ) {
814792 defer netnsutils .SetupTestOSContext (t )()
793+ useStubFirewaller (t )
794+
815795 d := newDriver (storeutils .NewTempStore (t ))
816796 portallocator .Get ().ReleaseAll ()
817797
@@ -924,9 +904,9 @@ func getPortMapping() []types.PortBinding {
924904
925905func TestLinkContainers (t * testing.T ) {
926906 defer netnsutils .SetupTestOSContext (t )()
907+ useStubFirewaller (t )
927908
928909 d := newDriver (storeutils .NewTempStore (t ))
929- iptable := iptables .GetIptable (iptables .IPv4 )
930910
931911 config := & configuration {
932912 EnableIPTables : true ,
@@ -1003,47 +983,29 @@ func TestLinkContainers(t *testing.T) {
1003983 t .Fatalf ("Failed to program external connectivity: %v" , err )
1004984 }
1005985
1006- out , _ := iptable .Raw ("-L" , dockerChain )
1007- for _ , pm := range exposedPorts {
1008- regex := fmt .Sprintf ("%s dpt:%d" , pm .Proto .String (), pm .Port )
1009- re := regexp .MustCompile (regex )
1010- matches := re .FindAllString (string (out [:]), - 1 )
1011- if len (matches ) != 1 {
1012- t .Fatalf ("IP Tables programming failed %s" , string (out [:]))
1013- }
1014-
1015- regex = fmt .Sprintf ("%s spt:%d" , pm .Proto .String (), pm .Port )
1016- matched , _ := regexp .Match (regex , out [:])
1017- if ! matched {
1018- t .Fatalf ("IP Tables programming failed %s" , string (out [:]))
1019- }
986+ checkLink := func (expExists bool ) {
987+ t .Helper ()
988+ dnw , ok := d .networks ["net1" ]
989+ assert .Assert (t , ok )
990+ fnw := dnw .firewallerNetwork .(* firewaller.StubFirewallerNetwork )
991+ parentAddr , ok := netip .AddrFromSlice (te2 .iface .addr .IP )
992+ assert .Assert (t , ok )
993+ childAddr , ok := netip .AddrFromSlice (te1 .iface .addr .IP )
994+ assert .Assert (t , ok )
995+ exists := fnw .LinkExists (parentAddr , childAddr , exposedPorts )
996+ assert .Check (t , is .Equal (exists , expExists ))
1020997 }
998+ checkLink (true )
1021999
10221000 err = d .RevokeExternalConnectivity ("net1" , "ep2" )
10231001 if err != nil {
10241002 t .Fatalf ("Failed to revoke external connectivity: %v" , err )
10251003 }
1026-
10271004 err = d .Leave ("net1" , "ep2" )
10281005 if err != nil {
10291006 t .Fatal ("Failed to unlink ep1 and ep2" )
10301007 }
1031-
1032- out , _ = iptable .Raw ("-L" , dockerChain )
1033- for _ , pm := range exposedPorts {
1034- regex := fmt .Sprintf ("%s dpt:%d" , pm .Proto .String (), pm .Port )
1035- re := regexp .MustCompile (regex )
1036- matches := re .FindAllString (string (out [:]), - 1 )
1037- if len (matches ) != 0 {
1038- t .Fatalf ("Leave should have deleted relevant IPTables rules %s" , string (out [:]))
1039- }
1040-
1041- regex = fmt .Sprintf ("%s spt:%d" , pm .Proto .String (), pm .Port )
1042- matched , _ := regexp .Match (regex , out [:])
1043- if matched {
1044- t .Fatalf ("Leave should have deleted relevant IPTables rules %s" , string (out [:]))
1045- }
1046- }
1008+ checkLink (false )
10471009
10481010 // Error condition test with an invalid endpoint-id "ep4"
10491011 sbOptions = make (map [string ]interface {})
@@ -1056,25 +1018,8 @@ func TestLinkContainers(t *testing.T) {
10561018 t .Fatal (err )
10571019 }
10581020 err = d .ProgramExternalConnectivity (context .Background (), "net1" , "ep2" , sbOptions )
1059- if err != nil {
1060- out , _ = iptable .Raw ("-L" , dockerChain )
1061- for _ , pm := range exposedPorts {
1062- regex := fmt .Sprintf ("%s dpt:%d" , pm .Proto .String (), pm .Port )
1063- re := regexp .MustCompile (regex )
1064- matches := re .FindAllString (string (out [:]), - 1 )
1065- if len (matches ) != 0 {
1066- t .Fatalf ("Error handling should rollback relevant IPTables rules %s" , string (out [:]))
1067- }
1068-
1069- regex = fmt .Sprintf ("%s spt:%d" , pm .Proto .String (), pm .Port )
1070- matched , _ := regexp .Match (regex , out [:])
1071- if matched {
1072- t .Fatalf ("Error handling should rollback relevant IPTables rules %s" , string (out [:]))
1073- }
1074- }
1075- } else {
1076- t .Fatal ("Expected Join to fail given link conditions are not satisfied" )
1077- }
1021+ assert .Check (t , err != nil , "Expected Join to fail given link conditions are not satisfied" )
1022+ checkLink (false )
10781023}
10791024
10801025func TestValidateConfig (t * testing.T ) {
@@ -1396,6 +1341,14 @@ func TestCreateParallel(t *testing.T) {
13961341 }
13971342}
13981343
1344+ func useStubFirewaller (t * testing.T ) {
1345+ origNewFirewaller := newFirewaller
1346+ newFirewaller = func (_ context.Context , config firewaller.Config ) (firewaller.Firewaller , error ) {
1347+ return firewaller .NewStubFirewaller (config ), nil
1348+ }
1349+ t .Cleanup (func () { newFirewaller = origNewFirewaller })
1350+ }
1351+
13991352// Regression test for https://github.com/moby/moby/issues/46445
14001353func TestSetupIP6TablesWithHostIPv4 (t * testing.T ) {
14011354 defer netnsutils .SetupTestOSContext (t )()
0 commit comments