github.com/aporeto-inc/trireme-lib@v10.358.0+incompatible/controller/internal/enforcer/acls/acl_test.go (about)

     1  package acls
     2  
     3  import (
     4  	"net"
     5  	"testing"
     6  
     7  	. "github.com/smartystreets/goconvey/convey"
     8  	"go.aporeto.io/enforcerd/trireme-lib/controller/constants"
     9  	"go.aporeto.io/enforcerd/trireme-lib/controller/pkg/packet"
    10  	"go.aporeto.io/enforcerd/trireme-lib/policy"
    11  )
    12  
    13  var (
    14  	rules = policy.IPRuleList{
    15  		policy.IPRule{
    16  			Addresses: []string{"172.0.0.0/8"},
    17  			Ports:     []string{"400:500"},
    18  			Protocols: []string{constants.TCPProtoNum},
    19  			Policy: &policy.FlowPolicy{
    20  				Action:   policy.Accept,
    21  				PolicyID: "tcp172/8"},
    22  		},
    23  		policy.IPRule{
    24  			Addresses: []string{"172.17.0.0/16"},
    25  			Ports:     []string{"400:500"},
    26  			Protocols: []string{constants.TCPProtoNum},
    27  			Policy: &policy.FlowPolicy{
    28  				Action:   policy.Accept,
    29  				PolicyID: "tcp172.17/16"},
    30  		},
    31  		policy.IPRule{
    32  			Addresses: []string{"192.168.100.0/24"},
    33  			Protocols: []string{constants.TCPProtoNum},
    34  			Ports:     []string{"80"},
    35  			Policy: &policy.FlowPolicy{
    36  				Action:   policy.Accept,
    37  				PolicyID: "tcp192.168.100/24"},
    38  		},
    39  		policy.IPRule{
    40  			Addresses: []string{"10.1.1.1"},
    41  			Protocols: []string{constants.TCPProtoNum},
    42  			Ports:     []string{"80"},
    43  			Policy: &policy.FlowPolicy{
    44  				Action:   policy.Accept,
    45  				PolicyID: "tcp10.1.1.1"}},
    46  		policy.IPRule{
    47  			Addresses: []string{"0.0.0.0/0"},
    48  			Protocols: []string{constants.TCPProtoNum},
    49  			Ports:     []string{"443"},
    50  			Policy: &policy.FlowPolicy{
    51  				Action:   policy.Accept,
    52  				PolicyID: "tcp0/0"}},
    53  		policy.IPRule{
    54  			Addresses: []string{"0.0.0.0/0"},
    55  			Protocols: []string{constants.UDPProtoNum},
    56  			Ports:     []string{"443"},
    57  			Policy: &policy.FlowPolicy{
    58  				Action:   policy.Accept,
    59  				PolicyID: "udp0/0"}},
    60  	}
    61  )
    62  
    63  func TestLookup(t *testing.T) {
    64  
    65  	Convey("Given a good DB", t, func() {
    66  
    67  		a := newACL()
    68  		So(a, ShouldNotBeNil)
    69  		for _, r := range rules {
    70  			err := a.addRule(r)
    71  			So(err, ShouldBeNil)
    72  		}
    73  
    74  		Convey("When I lookup for a matching address and a port range, I should get the right action", func() {
    75  			ip := net.ParseIP("172.17.0.1")
    76  			port := uint16(401)
    77  			r, p, err := a.getMatchingAction(ip.To4(), port, packet.IPProtocolTCP, nil)
    78  			So(err, ShouldBeNil)
    79  			So(p.Action, ShouldEqual, policy.Accept)
    80  			So(p.PolicyID, ShouldEqual, "tcp172.17/16")
    81  			So(r.Action, ShouldEqual, policy.Accept)
    82  			So(r.PolicyID, ShouldEqual, "tcp172.17/16")
    83  		})
    84  
    85  		Convey("When I lookup for a matching address with less specific match and a port range, I should get the right action", func() {
    86  			ip := net.ParseIP("172.16.0.1")
    87  			port := uint16(401)
    88  			r, p, err := a.getMatchingAction(ip.To4(), port, packet.IPProtocolTCP, nil)
    89  			So(err, ShouldBeNil)
    90  			So(p.Action, ShouldEqual, policy.Accept)
    91  			So(p.PolicyID, ShouldEqual, "tcp172/8")
    92  			So(r.Action, ShouldEqual, policy.Accept)
    93  			So(r.PolicyID, ShouldEqual, "tcp172/8")
    94  		})
    95  
    96  		Convey("When I lookup for a matching address exact port, I should get the right action", func() {
    97  			ip := net.ParseIP("192.168.100.1")
    98  			port := uint16(80)
    99  			r, p, err := a.getMatchingAction(ip.To4(), port, packet.IPProtocolTCP, nil)
   100  			So(err, ShouldBeNil)
   101  			So(p.Action, ShouldEqual, policy.Accept)
   102  			So(p.PolicyID, ShouldEqual, "tcp192.168.100/24")
   103  			So(r.Action, ShouldEqual, policy.Accept)
   104  			So(r.PolicyID, ShouldEqual, "tcp192.168.100/24")
   105  		})
   106  
   107  		Convey("When I lookup for a non matching address . I should get reject", func() {
   108  			ip := net.ParseIP("192.168.200.1")
   109  			port := uint16(80)
   110  			r, p, err := a.getMatchingAction(ip.To4(), port, packet.IPProtocolTCP, nil)
   111  			So(err, ShouldNotBeNil)
   112  			So(p, ShouldBeNil)
   113  			So(r, ShouldBeNil)
   114  		})
   115  
   116  		Convey("When I lookup for a matching address but failed port, I should get reject", func() {
   117  			ip := net.ParseIP("192.168.100.1")
   118  			port := uint16(600)
   119  			r, p, err := a.getMatchingAction(ip.To4(), port, packet.IPProtocolTCP, nil)
   120  			So(err, ShouldNotBeNil)
   121  			So(p, ShouldBeNil)
   122  			So(r, ShouldBeNil)
   123  		})
   124  
   125  		Convey("When I lookup for a matching exact address exact port, I should get the right action", func() {
   126  			ip := net.ParseIP("10.1.1.1")
   127  			port := uint16(80)
   128  			r, p, err := a.getMatchingAction(ip.To4(), port, packet.IPProtocolTCP, nil)
   129  			So(err, ShouldBeNil)
   130  			So(p.Action, ShouldEqual, policy.Accept)
   131  			So(p.PolicyID, ShouldEqual, "tcp10.1.1.1")
   132  			So(r.Action, ShouldEqual, policy.Accept)
   133  			So(r.PolicyID, ShouldEqual, "tcp10.1.1.1")
   134  		})
   135  
   136  	})
   137  }
   138  
   139  func TestICMPMatch(t *testing.T) {
   140  
   141  	var icmpRules = policy.IPRuleList{
   142  		policy.IPRule{
   143  			Addresses: []string{"0.0.0.0/0"},
   144  			Protocols: []string{"ICMP/8/1:3"},
   145  			Ports:     []string{},
   146  			Policy: &policy.FlowPolicy{
   147  				Action:   policy.Accept,
   148  				PolicyID: "icmp0/0-8/1:3",
   149  			},
   150  		},
   151  		policy.IPRule{
   152  			Addresses: []string{"684D:1111:222:3333:4444:5555:6:77"},
   153  			Protocols: []string{"ICMP6"},
   154  			Ports:     []string{},
   155  			Policy: &policy.FlowPolicy{
   156  				Action:   policy.Accept,
   157  				PolicyID: "icmp6",
   158  			},
   159  		},
   160  		policy.IPRule{
   161  			Addresses: []string{"192.0.2.1"},
   162  			Protocols: []string{"icmp"},
   163  			Ports:     []string{},
   164  			Policy: &policy.FlowPolicy{
   165  				Action:   policy.Accept,
   166  				PolicyID: "removeme",
   167  			},
   168  		},
   169  	}
   170  
   171  	Convey("Given a good DB", t, func() {
   172  
   173  		a := newACL()
   174  		So(a, ShouldNotBeNil)
   175  		for _, r := range icmpRules {
   176  			err := a.addRule(r)
   177  			So(err, ShouldBeNil)
   178  		}
   179  
   180  		Convey("When I lookup for a matching address for icmp but wrong type or code, I should get the right action", func() {
   181  			ip := net.ParseIP("172.17.0.1")
   182  			r, p, err := a.matchICMPRule(ip.To4(), 8, 2)
   183  			So(err, ShouldBeNil)
   184  			So(p.Action, ShouldEqual, policy.Accept)
   185  			So(p.PolicyID, ShouldEqual, "icmp0/0-8/1:3")
   186  			So(r.Action, ShouldEqual, policy.Accept)
   187  			So(r.PolicyID, ShouldEqual, "icmp0/0-8/1:3")
   188  		})
   189  
   190  		Convey("When I lookup for a matching address for icmp, I should not get a match", func() {
   191  			ip := net.ParseIP("172.17.0.1")
   192  			r, p, err := a.matchICMPRule(ip.To4(), 8, 4)
   193  			So(err, ShouldNotBeNil)
   194  			So(p, ShouldBeNil)
   195  			So(r, ShouldBeNil)
   196  		})
   197  
   198  		Convey("When I lookup for a matching address for icmp6, I should get the right action", func() {
   199  			ip := net.ParseIP("684D:1111:222:3333:4444:5555:6:77")
   200  			r, p, err := a.matchICMPRule(ip, 8, 1)
   201  			So(err, ShouldBeNil)
   202  			So(p.Action, ShouldEqual, policy.Accept)
   203  			So(p.PolicyID, ShouldEqual, "icmp6")
   204  			So(r.Action, ShouldEqual, policy.Accept)
   205  			So(r.PolicyID, ShouldEqual, "icmp6")
   206  		})
   207  
   208  		Convey("When I lookup for a non-matching address for icmp6, I should not get a match", func() {
   209  			ip := net.ParseIP("684D:1111:222:3333:4444:5555:6:77")
   210  			r, p, err := a.matchICMPRule(ip, 8, 1)
   211  			So(err, ShouldBeNil)
   212  			So(p.Action, ShouldEqual, policy.Accept)
   213  			So(p.PolicyID, ShouldEqual, "icmp6")
   214  			So(r.Action, ShouldEqual, policy.Accept)
   215  			So(r.PolicyID, ShouldEqual, "icmp6")
   216  		})
   217  	})
   218  }
   219  
   220  func TestICMPRemove(t *testing.T) {
   221  
   222  	var icmpRules = policy.IPRuleList{
   223  		policy.IPRule{
   224  			Addresses: []string{"192.0.2.1"},
   225  			Protocols: []string{"icmp"},
   226  			Ports:     []string{},
   227  			Policy: &policy.FlowPolicy{
   228  				Action:   policy.Accept,
   229  				PolicyID: "removeme",
   230  			},
   231  		},
   232  	}
   233  
   234  	removeMePolicy := &policy.FlowPolicy{
   235  		Action:   policy.Accept,
   236  		PolicyID: "removeme",
   237  	}
   238  
   239  	Convey("Given a good DB", t, func() {
   240  
   241  		a := newACL()
   242  		So(a, ShouldNotBeNil)
   243  		for _, r := range icmpRules {
   244  			err := a.addRule(r)
   245  			So(err, ShouldBeNil)
   246  		}
   247  
   248  		Convey("When I try to remove a rule which does not exist, then it should not error", func() {
   249  			ip := net.ParseIP("192.0.2.2")
   250  			err := a.removeFromCache(ip, 32, false, "icmp", nil, removeMePolicy)
   251  			So(err, ShouldBeNil)
   252  		})
   253  
   254  		Convey("When I try to remove a rule which does not match, then nothing should change", func() {
   255  			ip := net.ParseIP("192.0.2.1")
   256  			oldVal, ok := a.icmpCache.Get(ip, 32)
   257  			So(ok, ShouldBeTrue)
   258  			old := oldVal.([]*icmpRule)
   259  			So(old, ShouldNotBeEmpty)
   260  			err := a.removeFromCache(ip, 32, false, "icmp", nil, removeMePolicy)
   261  			So(err, ShouldBeNil)
   262  			newVal, ok := a.icmpCache.Get(ip, 32)
   263  			So(ok, ShouldBeTrue)
   264  			new := newVal.([]*icmpRule)
   265  			So(new, ShouldNotBeEmpty)
   266  			So(old, ShouldResemble, new)
   267  		})
   268  
   269  		Convey("When I try to remove a rule which matches, then it should get removed", func() {
   270  			ip := net.ParseIP("192.0.2.1")
   271  			oldVal, ok := a.icmpCache.Get(ip, 32)
   272  			So(ok, ShouldBeTrue)
   273  			old := oldVal.([]*icmpRule)
   274  			So(old, ShouldNotBeEmpty)
   275  			err := a.removeFromCache(ip, 32, false, "icmp", []string{}, removeMePolicy)
   276  			So(err, ShouldBeNil)
   277  			newVal, ok := a.icmpCache.Get(ip, 32)
   278  			So(ok, ShouldBeTrue)
   279  			new := newVal.([]*icmpRule)
   280  			So(new, ShouldBeEmpty)
   281  		})
   282  
   283  	})
   284  }
   285  
   286  func TestRemove(t *testing.T) {
   287  
   288  	// keep one policy here for a direct pointer comparison
   289  	policyOne := &policy.FlowPolicy{
   290  		Action:   policy.Accept,
   291  		PolicyID: "1",
   292  	}
   293  
   294  	removeRules := policy.IPRuleList{
   295  		policy.IPRule{
   296  			Addresses: []string{"192.0.2.1"},
   297  			Ports:     []string{"80"},
   298  			Protocols: []string{constants.TCPProtoNum},
   299  			Policy:    policyOne,
   300  		},
   301  		policy.IPRule{
   302  			Addresses: []string{"192.0.2.1"},
   303  			Ports:     []string{"80"},
   304  			Protocols: []string{constants.UDPProtoNum},
   305  			Policy: &policy.FlowPolicy{
   306  				Action:   policy.Accept,
   307  				PolicyID: "2",
   308  			},
   309  		},
   310  	}
   311  
   312  	// and one here for a content comparison
   313  	policyTwo := &policy.FlowPolicy{
   314  		Action:   policy.Accept,
   315  		PolicyID: "2",
   316  	}
   317  
   318  	Convey("Given a good DB", t, func() {
   319  
   320  		a := newACL()
   321  		So(a, ShouldNotBeNil)
   322  		for _, r := range removeRules {
   323  			err := a.addRule(r)
   324  			So(err, ShouldBeNil)
   325  		}
   326  
   327  		Convey("When I try to remove a rule with an unsupported protocol, then it should not error", func() {
   328  			ip := net.ParseIP("192.0.2.1")
   329  			err := a.removeFromCache(ip, 32, false, "unsupported", nil, nil)
   330  			So(err, ShouldBeNil)
   331  		})
   332  
   333  		Convey("When I try to remove a TCP rule which does not exist, then it should not error", func() {
   334  			ip := net.ParseIP("192.0.2.2")
   335  			err := a.removeFromCache(ip, 32, false, constants.TCPProtoNum, []string{"42"}, nil)
   336  			So(err, ShouldBeNil)
   337  		})
   338  
   339  		Convey("When I try to remove a TCP rule which cannot be parsed correctly, then it should error", func() {
   340  			ip := net.ParseIP("192.0.2.1")
   341  			err := a.removeFromCache(ip, 32, false, constants.TCPProtoNum, []string{"invalid port"}, nil)
   342  			So(err, ShouldNotBeNil)
   343  		})
   344  
   345  		Convey("When I try to remove a UDP rule which does not exist, then it should not error", func() {
   346  			ip := net.ParseIP("192.0.2.2")
   347  			err := a.removeFromCache(ip, 32, false, constants.UDPProtoNum, []string{"43"}, nil)
   348  			So(err, ShouldBeNil)
   349  		})
   350  
   351  		Convey("When I try to remove a UDP rule which cannot be parsed correctly, then it should error", func() {
   352  			ip := net.ParseIP("192.0.2.1")
   353  			err := a.removeFromCache(ip, 32, false, constants.UDPProtoNum, []string{"another invalid port"}, nil)
   354  			So(err, ShouldNotBeNil)
   355  		})
   356  
   357  		Convey("When I try to remove a TCP rule which does not match, then nothing should change", func() {
   358  			ip := net.ParseIP("192.0.2.1")
   359  			oldVal, ok := a.tcpCache.Get(ip, 32)
   360  			So(ok, ShouldBeTrue)
   361  			old := oldVal.(portActionList)
   362  			So(old, ShouldNotBeEmpty)
   363  			err := a.removeFromCache(ip, 32, false, constants.TCPProtoNum, []string{"44"}, policyOne)
   364  			So(err, ShouldBeNil)
   365  			newVal, ok := a.tcpCache.Get(ip, 32)
   366  			So(ok, ShouldBeTrue)
   367  			new := newVal.(portActionList)
   368  			So(new, ShouldNotBeEmpty)
   369  			So(old, ShouldResemble, new)
   370  		})
   371  
   372  		Convey("When I try to remove a TCP rule which matches, then it should get removed", func() {
   373  			ip := net.ParseIP("192.0.2.1")
   374  			oldVal, ok := a.tcpCache.Get(ip, 32)
   375  			So(ok, ShouldBeTrue)
   376  			old := oldVal.(portActionList)
   377  			So(old, ShouldNotBeEmpty)
   378  			oldLength := len(old)
   379  			err := a.removeFromCache(ip, 32, false, constants.TCPProtoNum, []string{"80"}, policyOne)
   380  			So(err, ShouldBeNil)
   381  			newVal, ok := a.tcpCache.Get(ip, 32)
   382  			So(ok, ShouldBeTrue)
   383  			new := newVal.(portActionList)
   384  			So(new, ShouldHaveLength, oldLength-1)
   385  		})
   386  
   387  		Convey("When I try to remove a UDP rule which does not match, then nothing should change", func() {
   388  			ip := net.ParseIP("192.0.2.1")
   389  			oldVal, ok := a.udpCache.Get(ip, 32)
   390  			So(ok, ShouldBeTrue)
   391  			old := oldVal.(portActionList)
   392  			So(old, ShouldNotBeEmpty)
   393  			err := a.removeFromCache(ip, 32, false, constants.UDPProtoNum, []string{"45"}, policyTwo)
   394  			So(err, ShouldBeNil)
   395  			newVal, ok := a.udpCache.Get(ip, 32)
   396  			So(ok, ShouldBeTrue)
   397  			new := newVal.(portActionList)
   398  			So(new, ShouldNotBeEmpty)
   399  			So(old, ShouldResemble, new)
   400  		})
   401  
   402  		Convey("When I try to remove a UDP rule which matches, then it should get removed", func() {
   403  			ip := net.ParseIP("192.0.2.1")
   404  			oldVal, ok := a.udpCache.Get(ip, 32)
   405  			So(ok, ShouldBeTrue)
   406  			old := oldVal.(portActionList)
   407  			So(old, ShouldNotBeEmpty)
   408  			oldLength := len(old)
   409  			err := a.removeFromCache(ip, 32, false, constants.UDPProtoNum, []string{"80"}, policyTwo)
   410  			So(err, ShouldBeNil)
   411  			newVal, ok := a.udpCache.Get(ip, 32)
   412  			So(ok, ShouldBeTrue)
   413  			new := newVal.(portActionList)
   414  			So(new, ShouldHaveLength, oldLength-1)
   415  		})
   416  	})
   417  }
   418  
   419  func TestObservedLookup(t *testing.T) {
   420  
   421  	ip1 := "200.17.0.0/17"
   422  	ip2 := "200.18.0.0/17"
   423  	ip3 := "200.0.0.0/9"
   424  	var (
   425  		rulesWithObservation = policy.IPRuleList{
   426  			policy.IPRule{
   427  				Addresses: []string{ip1},
   428  				Ports:     []string{"401"},
   429  				Protocols: []string{constants.TCPProtoNum},
   430  				Policy: &policy.FlowPolicy{
   431  					Action:        policy.Accept,
   432  					ObserveAction: policy.ObserveContinue,
   433  					PolicyID:      "observed-continue-tcp200.17/17"},
   434  			},
   435  			policy.IPRule{
   436  				Addresses: []string{ip2},
   437  				Ports:     []string{"401"},
   438  				Protocols: []string{constants.TCPProtoNum},
   439  				Policy: &policy.FlowPolicy{
   440  					Action:        policy.Accept,
   441  					ObserveAction: policy.ObserveApply,
   442  					PolicyID:      "observed-applied-tcp200.18/17"},
   443  			},
   444  			policy.IPRule{
   445  				Addresses: []string{ip3},
   446  				Ports:     []string{"401"},
   447  				Protocols: []string{constants.TCPProtoNum},
   448  				Policy: &policy.FlowPolicy{
   449  					Action:   policy.Accept,
   450  					PolicyID: "tcp200/9"},
   451  			},
   452  		}
   453  	)
   454  
   455  	Convey("Given a good DB", t, func() {
   456  		a := newACL()
   457  		So(a, ShouldNotBeNil)
   458  		for _, r := range rulesWithObservation {
   459  			err := a.addRule(r)
   460  			So(err, ShouldBeNil)
   461  		}
   462  
   463  		// Ensure all the elements are there in the cache
   464  		cidrs := []string{ip1, ip2, ip3}
   465  
   466  		for _, cidr := range cidrs {
   467  			ip, ipnet, _ := net.ParseCIDR(cidr)
   468  			size, _ := ipnet.Mask.Size()
   469  			_, ok := a.tcpCache.Get(ip, size)
   470  			So(ok, ShouldEqual, true)
   471  		}
   472  
   473  		Convey("When I lookup for a matching address and a port range, I should get the right action and observed action", func() {
   474  			ip := net.ParseIP("200.17.0.1")
   475  			port := uint16(401)
   476  			r, p, err := a.getMatchingAction(ip.To4(), port, packet.IPProtocolTCP, nil)
   477  			So(err, ShouldBeNil)
   478  			So(p.Action, ShouldEqual, policy.Accept)
   479  			So(p.PolicyID, ShouldEqual, "tcp200/9")
   480  			So(r.Action, ShouldEqual, policy.Accept)
   481  			So(r.PolicyID, ShouldEqual, "observed-continue-tcp200.17/17")
   482  		})
   483  
   484  		Convey("When I lookup for a matching address and a port range, I should get the observed action as applied", func() {
   485  			ip := net.ParseIP("200.18.0.1")
   486  			port := uint16(401)
   487  			r, p, err := a.getMatchingAction(ip.To4(), port, packet.IPProtocolTCP, nil)
   488  			So(err, ShouldBeNil)
   489  			So(p.Action, ShouldEqual, policy.Accept)
   490  			So(p.PolicyID, ShouldEqual, "observed-applied-tcp200.18/17")
   491  			So(r.Action, ShouldEqual, policy.Accept)
   492  			So(r.PolicyID, ShouldEqual, "observed-applied-tcp200.18/17")
   493  		})
   494  
   495  		Convey("When I lookup for a matching address and a port range with an already reported action of reject, I should get the observed action as applied", func() {
   496  			ip := net.ParseIP("200.18.0.1")
   497  			port := uint16(401)
   498  			preReported := &policy.FlowPolicy{
   499  				Action:   policy.Reject,
   500  				PolicyID: "preReportedPolicyID",
   501  			}
   502  			r, p, err := a.getMatchingAction(ip.To4(), port, packet.IPProtocolTCP, preReported)
   503  			So(err, ShouldBeNil)
   504  			So(p.Action, ShouldEqual, policy.Accept)
   505  			So(p.PolicyID, ShouldEqual, "observed-applied-tcp200.18/17")
   506  			So(r.Action, ShouldEqual, policy.Reject)
   507  			So(r.PolicyID, ShouldEqual, "preReportedPolicyID")
   508  		})
   509  	})
   510  }
   511  
   512  func TestNomatchLookup(t *testing.T) {
   513  
   514  	ip1 := "200.17.0.0/16"
   515  	ip2 := "200.18.0.0/16"
   516  	ip3 := "200.0.0.0/8"
   517  	var (
   518  		rulesWithNomatch = policy.IPRuleList{
   519  			policy.IPRule{
   520  				Addresses: []string{"!" + ip1},
   521  				Ports:     []string{"401"},
   522  				Protocols: []string{constants.TCPProtoNum},
   523  				Policy: &policy.FlowPolicy{
   524  					Action:   policy.Accept,
   525  					PolicyID: "nomatch-tcp200.17/16"},
   526  			},
   527  			policy.IPRule{
   528  				Addresses: []string{"!" + ip2},
   529  				Ports:     []string{"401"},
   530  				Protocols: []string{constants.TCPProtoNum},
   531  				Policy: &policy.FlowPolicy{
   532  					Action:   policy.Accept,
   533  					PolicyID: "nomatch-tcp200.18/16"},
   534  			},
   535  			policy.IPRule{
   536  				Addresses: []string{ip3},
   537  				Ports:     []string{"401"},
   538  				Protocols: []string{constants.TCPProtoNum},
   539  				Policy: &policy.FlowPolicy{
   540  					Action:   policy.Accept,
   541  					PolicyID: "tcp200/8"},
   542  			},
   543  		}
   544  	)
   545  
   546  	Convey("Given a good DB", t, func() {
   547  		a := newACL()
   548  		So(a, ShouldNotBeNil)
   549  		for _, r := range rulesWithNomatch {
   550  			err := a.addRule(r)
   551  			So(err, ShouldBeNil)
   552  		}
   553  
   554  		// Ensure all the elements are there in the cache
   555  		cidrs := []string{ip1, ip2, ip3}
   556  
   557  		for _, cidr := range cidrs {
   558  			ip, ipnet, _ := net.ParseCIDR(cidr)
   559  			size, _ := ipnet.Mask.Size()
   560  			_, ok := a.tcpCache.Get(ip, size)
   561  			So(ok, ShouldEqual, true)
   562  		}
   563  
   564  		Convey("When I lookup for a nomatch address and a port range, I should get nomatch", func() {
   565  			ip := net.ParseIP("200.17.0.1")
   566  			port := uint16(401)
   567  			_, _, err := a.getMatchingAction(ip.To4(), port, packet.IPProtocolTCP, nil)
   568  			So(err, ShouldNotBeNil)
   569  		})
   570  
   571  		Convey("When I lookup for another nomatch address and a port range, I should get nomatch", func() {
   572  			ip := net.ParseIP("200.18.0.1")
   573  			port := uint16(401)
   574  			_, _, err := a.getMatchingAction(ip.To4(), port, packet.IPProtocolTCP, nil)
   575  			So(err, ShouldNotBeNil)
   576  		})
   577  
   578  		Convey("When I lookup for a matching address and a port range, I should get the accept action", func() {
   579  			ip := net.ParseIP("200.19.0.1")
   580  			port := uint16(401)
   581  			r, p, err := a.getMatchingAction(ip.To4(), port, packet.IPProtocolTCP, nil)
   582  			So(err, ShouldBeNil)
   583  			So(p.Action, ShouldEqual, policy.Accept)
   584  			So(p.PolicyID, ShouldEqual, "tcp200/8")
   585  			So(r.Action, ShouldEqual, policy.Accept)
   586  			So(r.PolicyID, ShouldEqual, "tcp200/8")
   587  		})
   588  	})
   589  }