github.com/imran-kn/cilium-fork@v1.6.9/pkg/policy/rule_test.go (about)

     1  // Copyright 2016-2019 Authors of Cilium
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // +build !privileged_tests
    16  
    17  package policy
    18  
    19  import (
    20  	"bytes"
    21  	"fmt"
    22  	"net"
    23  
    24  	"github.com/cilium/cilium/api/v1/models"
    25  	"github.com/cilium/cilium/pkg/checker"
    26  	"github.com/cilium/cilium/pkg/identity"
    27  	identity2 "github.com/cilium/cilium/pkg/identity"
    28  	"github.com/cilium/cilium/pkg/labels"
    29  	"github.com/cilium/cilium/pkg/policy/api"
    30  
    31  	logging "github.com/op/go-logging"
    32  	. "gopkg.in/check.v1"
    33  )
    34  
    35  func (ds *PolicyTestSuite) TestL4Policy(c *C) {
    36  	toBar := &SearchContext{To: labels.ParseSelectLabelArray("bar")}
    37  	fromBar := &SearchContext{From: labels.ParseSelectLabelArray("bar")}
    38  	toFoo := &SearchContext{To: labels.ParseSelectLabelArray("foo")}
    39  	fromFoo := &SearchContext{From: labels.ParseSelectLabelArray("foo")}
    40  
    41  	rule1 := &rule{
    42  		Rule: api.Rule{
    43  			EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
    44  			Ingress: []api.IngressRule{
    45  				{
    46  					ToPorts: []api.PortRule{{
    47  						Ports: []api.PortProtocol{
    48  							{Port: "80", Protocol: api.ProtoTCP},
    49  							{Port: "8080", Protocol: api.ProtoTCP},
    50  						},
    51  						Rules: &api.L7Rules{
    52  							HTTP: []api.PortRuleHTTP{
    53  								{Method: "GET", Path: "/"},
    54  							},
    55  						},
    56  					}},
    57  				},
    58  			},
    59  			Egress: []api.EgressRule{
    60  				{
    61  					ToPorts: []api.PortRule{{
    62  						Ports: []api.PortProtocol{
    63  							{Port: "3000", Protocol: api.ProtoAny},
    64  						},
    65  					}},
    66  				},
    67  			},
    68  		},
    69  	}
    70  
    71  	l7rules := api.L7Rules{
    72  		HTTP: []api.PortRuleHTTP{{Path: "/", Method: "GET"}},
    73  	}
    74  	l7map := L7DataMap{
    75  		wildcardCachedSelector: l7rules,
    76  	}
    77  
    78  	expected := NewL4Policy(0)
    79  	expected.Ingress["80/TCP"] = &L4Filter{
    80  		Port: 80, Protocol: api.ProtoTCP, U8Proto: 6,
    81  		allowsAllAtL3:   true,
    82  		CachedSelectors: CachedSelectorSlice{wildcardCachedSelector},
    83  		L7Parser:        "http", L7RulesPerEp: l7map, Ingress: true,
    84  		DerivedFromRules: labels.LabelArrayList{nil},
    85  	}
    86  	expected.Ingress["8080/TCP"] = &L4Filter{
    87  		Port: 8080, Protocol: api.ProtoTCP, U8Proto: 6,
    88  		allowsAllAtL3:   true,
    89  		CachedSelectors: CachedSelectorSlice{wildcardCachedSelector},
    90  		L7Parser:        "http", L7RulesPerEp: l7map, Ingress: true,
    91  		DerivedFromRules: labels.LabelArrayList{nil},
    92  	}
    93  
    94  	expected.Egress["3000/TCP"] = &L4Filter{
    95  		Port: 3000, Protocol: api.ProtoTCP, U8Proto: 6, Ingress: false,
    96  		allowsAllAtL3:    true,
    97  		CachedSelectors:  CachedSelectorSlice{wildcardCachedSelector},
    98  		L7RulesPerEp:     L7DataMap{},
    99  		DerivedFromRules: labels.LabelArrayList{nil},
   100  	}
   101  	expected.Egress["3000/UDP"] = &L4Filter{
   102  		Port: 3000, Protocol: api.ProtoUDP, U8Proto: 17, Ingress: false,
   103  		allowsAllAtL3:    true,
   104  		CachedSelectors:  CachedSelectorSlice{wildcardCachedSelector},
   105  		L7RulesPerEp:     L7DataMap{},
   106  		DerivedFromRules: labels.LabelArrayList{nil},
   107  	}
   108  
   109  	ingressState := traceState{}
   110  	egressState := traceState{}
   111  	res := NewL4Policy(0)
   112  	var err error
   113  	res.Ingress, err = rule1.resolveIngressPolicy(toBar, &ingressState, L4PolicyMap{}, nil, testSelectorCache)
   114  	c.Assert(err, IsNil)
   115  	c.Assert(res.Ingress, Not(IsNil))
   116  
   117  	res.Egress, err = rule1.resolveEgressPolicy(fromBar, &egressState, L4PolicyMap{}, nil, testSelectorCache)
   118  	c.Assert(err, IsNil)
   119  	c.Assert(res.Egress, Not(IsNil))
   120  
   121  	c.Assert(res, checker.Equals, expected)
   122  	c.Assert(ingressState.selectedRules, Equals, 1)
   123  	c.Assert(ingressState.matchedRules, Equals, 0)
   124  
   125  	c.Assert(egressState.selectedRules, Equals, 1)
   126  	c.Assert(egressState.matchedRules, Equals, 0)
   127  	res.Detach(testSelectorCache)
   128  	expected.Detach(testSelectorCache)
   129  
   130  	// Foo isn't selected in the rule1's policy.
   131  	ingressState = traceState{}
   132  	egressState = traceState{}
   133  
   134  	res1, err := rule1.resolveIngressPolicy(toFoo, &ingressState, L4PolicyMap{}, nil, testSelectorCache)
   135  	c.Assert(err, IsNil)
   136  	res2, err := rule1.resolveEgressPolicy(fromFoo, &ingressState, L4PolicyMap{}, nil, testSelectorCache)
   137  	c.Assert(err, IsNil)
   138  
   139  	c.Assert(res1, IsNil)
   140  	c.Assert(res2, IsNil)
   141  	c.Assert(ingressState.selectedRules, Equals, 0)
   142  	c.Assert(ingressState.matchedRules, Equals, 0)
   143  	c.Assert(egressState.selectedRules, Equals, 0)
   144  	c.Assert(egressState.matchedRules, Equals, 0)
   145  
   146  	// This rule actually overlaps with the existing ingress "http" rule,
   147  	// so we'd expect it to merge.
   148  	rule2 := &rule{
   149  		Rule: api.Rule{
   150  			EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
   151  			Ingress: []api.IngressRule{
   152  				{
   153  					ToPorts: []api.PortRule{{
   154  						Ports: []api.PortProtocol{
   155  							{Port: "80", Protocol: api.ProtoTCP},
   156  						},
   157  					}},
   158  				},
   159  				{
   160  					ToPorts: []api.PortRule{{
   161  						Ports: []api.PortProtocol{
   162  							{Port: "80", Protocol: api.ProtoTCP},
   163  						},
   164  						Rules: &api.L7Rules{
   165  							HTTP: []api.PortRuleHTTP{
   166  								{Method: "GET", Path: "/"},
   167  							},
   168  						},
   169  					}},
   170  				},
   171  			},
   172  			Egress: []api.EgressRule{
   173  				{
   174  					ToPorts: []api.PortRule{{
   175  						Ports: []api.PortProtocol{
   176  							{Port: "3000", Protocol: api.ProtoAny},
   177  						},
   178  					}},
   179  				},
   180  			},
   181  		},
   182  	}
   183  
   184  	expected = NewL4Policy(0)
   185  	expected.Ingress["80/TCP"] = &L4Filter{
   186  		Port:            80,
   187  		Protocol:        api.ProtoTCP,
   188  		U8Proto:         6,
   189  		allowsAllAtL3:   true,
   190  		CachedSelectors: CachedSelectorSlice{wildcardCachedSelector},
   191  		L7Parser:        ParserTypeHTTP,
   192  		L7RulesPerEp: L7DataMap{
   193  			wildcardCachedSelector: api.L7Rules{
   194  				HTTP: []api.PortRuleHTTP{{Path: "/", Method: "GET"}},
   195  			},
   196  		},
   197  		Ingress:          true,
   198  		DerivedFromRules: labels.LabelArrayList{nil, nil},
   199  	}
   200  	expected.Egress["3000/TCP"] = &L4Filter{
   201  		Port: 3000, Protocol: api.ProtoTCP, U8Proto: 6, Ingress: false,
   202  		allowsAllAtL3:    true,
   203  		CachedSelectors:  CachedSelectorSlice{wildcardCachedSelector},
   204  		L7RulesPerEp:     L7DataMap{},
   205  		DerivedFromRules: labels.LabelArrayList{nil},
   206  	}
   207  	expected.Egress["3000/UDP"] = &L4Filter{
   208  		Port: 3000, Protocol: api.ProtoUDP, U8Proto: 17, Ingress: false,
   209  		allowsAllAtL3:    true,
   210  		CachedSelectors:  CachedSelectorSlice{wildcardCachedSelector},
   211  		L7RulesPerEp:     L7DataMap{},
   212  		DerivedFromRules: labels.LabelArrayList{nil},
   213  	}
   214  
   215  	ingressState = traceState{}
   216  	egressState = traceState{}
   217  	res = NewL4Policy(0)
   218  	res.Ingress, err = rule2.resolveIngressPolicy(toBar, &ingressState, L4PolicyMap{}, nil, testSelectorCache)
   219  	c.Assert(err, IsNil)
   220  	c.Assert(res.Ingress, Not(IsNil))
   221  
   222  	res.Egress, err = rule2.resolveEgressPolicy(fromBar, &egressState, L4PolicyMap{}, nil, testSelectorCache)
   223  	c.Assert(err, IsNil)
   224  	c.Assert(res.Egress, Not(IsNil))
   225  
   226  	c.Assert(len(res.Ingress), Equals, 1)
   227  	c.Assert(res, checker.Equals, expected)
   228  	c.Assert(ingressState.selectedRules, Equals, 1)
   229  	c.Assert(ingressState.matchedRules, Equals, 0)
   230  
   231  	c.Assert(egressState.selectedRules, Equals, 1)
   232  	c.Assert(egressState.matchedRules, Equals, 0)
   233  	res.Detach(testSelectorCache)
   234  	expected.Detach(testSelectorCache)
   235  
   236  	ingressState = traceState{}
   237  	egressState = traceState{}
   238  
   239  	res1, err = rule2.resolveIngressPolicy(toFoo, &ingressState, L4PolicyMap{}, nil, testSelectorCache)
   240  	c.Assert(err, IsNil)
   241  	c.Assert(res1, IsNil)
   242  
   243  	res2, err = rule2.resolveEgressPolicy(fromFoo, &egressState, L4PolicyMap{}, nil, testSelectorCache)
   244  	c.Assert(err, IsNil)
   245  	c.Assert(res2, IsNil)
   246  
   247  	c.Assert(ingressState.selectedRules, Equals, 0)
   248  	c.Assert(ingressState.matchedRules, Equals, 0)
   249  
   250  	c.Assert(egressState.selectedRules, Equals, 0)
   251  	c.Assert(egressState.matchedRules, Equals, 0)
   252  }
   253  
   254  func (ds *PolicyTestSuite) TestMergeL4PolicyIngress(c *C) {
   255  	toBar := &SearchContext{To: labels.ParseSelectLabelArray("bar")}
   256  	//toFoo := &SearchContext{To: labels.ParseSelectLabelArray("foo")}
   257  
   258  	rule1 := &rule{
   259  		Rule: api.Rule{
   260  			EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
   261  			Ingress: []api.IngressRule{
   262  				{
   263  					FromEndpoints: []api.EndpointSelector{fooSelector},
   264  					ToPorts: []api.PortRule{{
   265  						Ports: []api.PortProtocol{
   266  							{Port: "80", Protocol: api.ProtoTCP},
   267  						},
   268  					}},
   269  				},
   270  				{
   271  					FromEndpoints: []api.EndpointSelector{bazSelector},
   272  					ToPorts: []api.PortRule{{
   273  						Ports: []api.PortProtocol{
   274  							{Port: "80", Protocol: api.ProtoTCP},
   275  						},
   276  					}},
   277  				},
   278  			},
   279  		},
   280  	}
   281  
   282  	mergedES := CachedSelectorSlice{cachedFooSelector, cachedBazSelector}
   283  	expected := L4PolicyMap{"80/TCP": &L4Filter{
   284  		Port: 80, Protocol: api.ProtoTCP, U8Proto: 6, CachedSelectors: mergedES,
   285  		L7Parser: ParserTypeNone, L7RulesPerEp: L7DataMap{}, Ingress: true,
   286  		DerivedFromRules: labels.LabelArrayList{nil, nil},
   287  	}}
   288  
   289  	state := traceState{}
   290  	res, err := rule1.resolveIngressPolicy(toBar, &state, L4PolicyMap{}, nil, testSelectorCache)
   291  	c.Assert(err, IsNil)
   292  	c.Assert(res, Not(IsNil))
   293  	c.Assert(res, checker.Equals, expected)
   294  	c.Assert(state.selectedRules, Equals, 1)
   295  	c.Assert(state.matchedRules, Equals, 0)
   296  	res.Detach(testSelectorCache)
   297  	expected.Detach(testSelectorCache)
   298  }
   299  
   300  func (ds *PolicyTestSuite) TestMergeL4PolicyEgress(c *C) {
   301  
   302  	buffer := new(bytes.Buffer)
   303  	fromBar := &SearchContext{
   304  		From:    labels.ParseSelectLabelArray("bar"),
   305  		Logging: logging.NewLogBackend(buffer, "", 0),
   306  		Trace:   TRACE_VERBOSE,
   307  	}
   308  
   309  	// bar can access foo with TCP on port 80, and baz with TCP on port 80.
   310  	rule1 := &rule{
   311  		Rule: api.Rule{
   312  			EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
   313  			Egress: []api.EgressRule{
   314  				{
   315  					ToEndpoints: []api.EndpointSelector{fooSelector},
   316  					ToPorts: []api.PortRule{{
   317  						Ports: []api.PortProtocol{
   318  							{Port: "80", Protocol: api.ProtoTCP},
   319  						},
   320  					}},
   321  				},
   322  				{
   323  					ToEndpoints: []api.EndpointSelector{bazSelector},
   324  					ToPorts: []api.PortRule{{
   325  						Ports: []api.PortProtocol{
   326  							{Port: "80", Protocol: api.ProtoTCP},
   327  						},
   328  					}},
   329  				},
   330  			},
   331  		},
   332  	}
   333  
   334  	mergedES := CachedSelectorSlice{cachedFooSelector, cachedBazSelector}
   335  	expected := L4PolicyMap{"80/TCP": &L4Filter{
   336  		Port: 80, Protocol: api.ProtoTCP, U8Proto: 6, CachedSelectors: mergedES,
   337  		L7Parser: ParserTypeNone, L7RulesPerEp: L7DataMap{}, Ingress: false,
   338  		DerivedFromRules: labels.LabelArrayList{nil, nil},
   339  	}}
   340  
   341  	state := traceState{}
   342  	res, err := rule1.resolveEgressPolicy(fromBar, &state, L4PolicyMap{}, nil, testSelectorCache)
   343  
   344  	c.Log(buffer)
   345  
   346  	c.Assert(err, IsNil)
   347  	c.Assert(res, Not(IsNil))
   348  	c.Assert(res, checker.Equals, expected)
   349  	c.Assert(state.selectedRules, Equals, 1)
   350  	c.Assert(state.matchedRules, Equals, 0)
   351  	res.Detach(testSelectorCache)
   352  	expected.Detach(testSelectorCache)
   353  }
   354  
   355  func (ds *PolicyTestSuite) TestMergeL7PolicyIngress(c *C) {
   356  	toBar := &SearchContext{To: labels.ParseSelectLabelArray("bar")}
   357  	toFoo := &SearchContext{To: labels.ParseSelectLabelArray("foo")}
   358  
   359  	fooSelectorSlice := []api.EndpointSelector{
   360  		fooSelector,
   361  	}
   362  	rule1 := &rule{
   363  		Rule: api.Rule{
   364  			EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
   365  			Ingress: []api.IngressRule{
   366  				{
   367  					ToPorts: []api.PortRule{{
   368  						Ports: []api.PortProtocol{
   369  							{Port: "80", Protocol: api.ProtoTCP},
   370  						},
   371  					}},
   372  				},
   373  				{
   374  					ToPorts: []api.PortRule{{
   375  						Ports: []api.PortProtocol{
   376  							{Port: "80", Protocol: api.ProtoTCP},
   377  						},
   378  						Rules: &api.L7Rules{
   379  							HTTP: []api.PortRuleHTTP{
   380  								{Method: "GET", Path: "/"},
   381  							},
   382  						},
   383  					}},
   384  				},
   385  				{
   386  					FromEndpoints: fooSelectorSlice,
   387  					ToPorts: []api.PortRule{{
   388  						Ports: []api.PortProtocol{
   389  							{Port: "80", Protocol: api.ProtoTCP},
   390  						},
   391  						Rules: &api.L7Rules{
   392  							HTTP: []api.PortRuleHTTP{
   393  								{Method: "GET", Path: "/"},
   394  							},
   395  						},
   396  					}},
   397  				},
   398  			},
   399  		},
   400  	}
   401  
   402  	expected := L4PolicyMap{"80/TCP": &L4Filter{
   403  		Port:            80,
   404  		Protocol:        api.ProtoTCP,
   405  		U8Proto:         6,
   406  		allowsAllAtL3:   true,
   407  		CachedSelectors: CachedSelectorSlice{wildcardCachedSelector, cachedFooSelector},
   408  		L7Parser:        ParserTypeHTTP,
   409  		L7RulesPerEp: L7DataMap{
   410  			wildcardCachedSelector: api.L7Rules{
   411  				HTTP: []api.PortRuleHTTP{{Path: "/", Method: "GET"}},
   412  			},
   413  			cachedFooSelector: api.L7Rules{
   414  				HTTP: []api.PortRuleHTTP{{Path: "/", Method: "GET"}},
   415  			},
   416  		},
   417  		Ingress:          true,
   418  		DerivedFromRules: labels.LabelArrayList{nil, nil, nil},
   419  	}}
   420  
   421  	state := traceState{}
   422  	res, err := rule1.resolveIngressPolicy(toBar, &state, L4PolicyMap{}, nil, testSelectorCache)
   423  	c.Assert(err, IsNil)
   424  	c.Assert(res, Not(IsNil))
   425  	c.Assert(res, checker.Equals, expected)
   426  	c.Assert(state.selectedRules, Equals, 1)
   427  	c.Assert(state.matchedRules, Equals, 0)
   428  	res.Detach(testSelectorCache)
   429  	expected.Detach(testSelectorCache)
   430  
   431  	state = traceState{}
   432  	res, err = rule1.resolveIngressPolicy(toFoo, &state, L4PolicyMap{}, nil, testSelectorCache)
   433  	c.Assert(err, IsNil)
   434  	c.Assert(res, IsNil)
   435  	c.Assert(state.selectedRules, Equals, 0)
   436  	c.Assert(state.matchedRules, Equals, 0)
   437  
   438  	rule2 := &rule{
   439  		Rule: api.Rule{
   440  			EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
   441  			Ingress: []api.IngressRule{
   442  				{
   443  					ToPorts: []api.PortRule{{
   444  						Ports: []api.PortProtocol{
   445  							{Port: "80", Protocol: api.ProtoTCP},
   446  						},
   447  						Rules: &api.L7Rules{
   448  							Kafka: []api.PortRuleKafka{
   449  								{Topic: "foo"},
   450  							},
   451  						},
   452  					}},
   453  				},
   454  				{
   455  					FromEndpoints: fooSelectorSlice,
   456  					ToPorts: []api.PortRule{{
   457  						Ports: []api.PortProtocol{
   458  							{Port: "80", Protocol: api.ProtoTCP},
   459  						},
   460  						Rules: &api.L7Rules{
   461  							Kafka: []api.PortRuleKafka{
   462  								{Topic: "foo"},
   463  							},
   464  						},
   465  					}},
   466  				},
   467  			},
   468  		},
   469  	}
   470  
   471  	l7rules := api.L7Rules{
   472  		Kafka: []api.PortRuleKafka{{Topic: "foo"}},
   473  	}
   474  	l7map := L7DataMap{
   475  		wildcardCachedSelector: l7rules,
   476  		cachedFooSelector:      l7rules,
   477  	}
   478  
   479  	expected = L4PolicyMap{"80/TCP": &L4Filter{
   480  		Port: 80, Protocol: api.ProtoTCP, U8Proto: 6,
   481  		allowsAllAtL3:   true,
   482  		CachedSelectors: CachedSelectorSlice{wildcardCachedSelector, cachedFooSelector},
   483  		L7Parser:        "kafka", L7RulesPerEp: l7map, Ingress: true,
   484  		DerivedFromRules: labels.LabelArrayList{nil, nil},
   485  	}}
   486  
   487  	state = traceState{}
   488  	res, err = rule2.resolveIngressPolicy(toBar, &state, L4PolicyMap{}, nil, testSelectorCache)
   489  	c.Assert(err, IsNil)
   490  	c.Assert(res, Not(IsNil))
   491  	c.Assert(res, checker.Equals, expected)
   492  	c.Assert(state.selectedRules, Equals, 1)
   493  	c.Assert(state.matchedRules, Equals, 0)
   494  	res.Detach(testSelectorCache)
   495  	expected.Detach(testSelectorCache)
   496  
   497  	state = traceState{}
   498  	res, err = rule2.resolveIngressPolicy(toFoo, &state, L4PolicyMap{}, nil, testSelectorCache)
   499  	c.Assert(err, IsNil)
   500  	c.Assert(res, IsNil)
   501  	c.Assert(state.selectedRules, Equals, 0)
   502  	c.Assert(state.matchedRules, Equals, 0)
   503  
   504  	// Resolve rule1's policy, then try to add rule2.
   505  	res, err = rule1.resolveIngressPolicy(toBar, &state, L4PolicyMap{}, nil, testSelectorCache)
   506  	c.Assert(err, IsNil)
   507  	c.Assert(res, Not(IsNil))
   508  
   509  	state = traceState{}
   510  	_, err = rule2.resolveIngressPolicy(toBar, &state, res, nil, testSelectorCache)
   511  
   512  	c.Assert(err, Not(IsNil))
   513  	res.Detach(testSelectorCache)
   514  
   515  	// Similar to 'rule2', but with different topics for the l3-dependent
   516  	// rule and the l4-only rule.
   517  	rule3 := &rule{
   518  		Rule: api.Rule{
   519  			EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
   520  			Ingress: []api.IngressRule{
   521  				{
   522  					FromEndpoints: fooSelectorSlice,
   523  					ToPorts: []api.PortRule{{
   524  						Ports: []api.PortProtocol{
   525  							{Port: "80", Protocol: api.ProtoTCP},
   526  						},
   527  						Rules: &api.L7Rules{
   528  							Kafka: []api.PortRuleKafka{
   529  								{Topic: "foo"},
   530  							},
   531  						},
   532  					}},
   533  				},
   534  				{
   535  					FromEndpoints: []api.EndpointSelector{api.WildcardEndpointSelector},
   536  					ToPorts: []api.PortRule{{
   537  						Ports: []api.PortProtocol{
   538  							{Port: "80", Protocol: api.ProtoTCP},
   539  						},
   540  						Rules: &api.L7Rules{
   541  							Kafka: []api.PortRuleKafka{
   542  								{Topic: "bar"},
   543  							},
   544  						},
   545  					}},
   546  				},
   547  			},
   548  		},
   549  	}
   550  
   551  	fooRules := api.L7Rules{
   552  		Kafka: []api.PortRuleKafka{{Topic: "foo"}},
   553  	}
   554  
   555  	barRules := api.L7Rules{
   556  		Kafka: []api.PortRuleKafka{{Topic: "bar"}},
   557  	}
   558  
   559  	// The L3-dependent L7 rules are not merged together.
   560  	l7map = L7DataMap{
   561  		cachedFooSelector:      fooRules,
   562  		wildcardCachedSelector: barRules,
   563  	}
   564  	expected = L4PolicyMap{"80/TCP": &L4Filter{
   565  		Port: 80, Protocol: api.ProtoTCP, U8Proto: 6,
   566  		allowsAllAtL3:   true,
   567  		CachedSelectors: CachedSelectorSlice{cachedFooSelector, wildcardCachedSelector},
   568  		L7Parser:        "kafka", L7RulesPerEp: l7map, Ingress: true,
   569  		DerivedFromRules: labels.LabelArrayList{nil, nil},
   570  	}}
   571  
   572  	state = traceState{}
   573  	res, err = rule3.resolveIngressPolicy(toBar, &state, L4PolicyMap{}, nil, testSelectorCache)
   574  	c.Assert(err, IsNil)
   575  	c.Assert(res, Not(IsNil))
   576  	c.Assert(res, checker.Equals, expected)
   577  	c.Assert(state.selectedRules, Equals, 1)
   578  	c.Assert(state.matchedRules, Equals, 0)
   579  	res.Detach(testSelectorCache)
   580  	expected.Detach(testSelectorCache)
   581  }
   582  
   583  func (ds *PolicyTestSuite) TestMergeL7PolicyEgress(c *C) {
   584  	fromBar := &SearchContext{From: labels.ParseSelectLabelArray("bar")}
   585  	fromFoo := &SearchContext{From: labels.ParseSelectLabelArray("foo")}
   586  
   587  	fooSelector := []api.EndpointSelector{
   588  		api.NewESFromLabels(labels.ParseSelectLabel("foo")),
   589  	}
   590  
   591  	rule1 := &rule{
   592  		Rule: api.Rule{
   593  			EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
   594  			Egress: []api.EgressRule{
   595  				{
   596  					ToPorts: []api.PortRule{{
   597  						Ports: []api.PortProtocol{
   598  							{Port: "80", Protocol: api.ProtoTCP},
   599  						},
   600  					}},
   601  				},
   602  				{
   603  					ToPorts: []api.PortRule{{
   604  						Ports: []api.PortProtocol{
   605  							{Port: "80", Protocol: api.ProtoTCP},
   606  						},
   607  						Rules: &api.L7Rules{
   608  							HTTP: []api.PortRuleHTTP{
   609  								{Method: "GET", Path: "/public"},
   610  							},
   611  						},
   612  					}},
   613  				},
   614  				{
   615  					ToEndpoints: fooSelector,
   616  					ToPorts: []api.PortRule{{
   617  						Ports: []api.PortProtocol{
   618  							{Port: "80", Protocol: api.ProtoTCP},
   619  						},
   620  						Rules: &api.L7Rules{
   621  							HTTP: []api.PortRuleHTTP{
   622  								{Method: "GET", Path: "/private"},
   623  							},
   624  						},
   625  					}},
   626  				},
   627  			},
   628  		},
   629  	}
   630  
   631  	expected := L4PolicyMap{"80/TCP": &L4Filter{
   632  		Port: 80, Protocol: api.ProtoTCP, U8Proto: 6,
   633  		allowsAllAtL3:   true,
   634  		CachedSelectors: CachedSelectorSlice{wildcardCachedSelector, cachedFooSelector},
   635  		L7Parser:        ParserTypeHTTP,
   636  		L7RulesPerEp: L7DataMap{
   637  			wildcardCachedSelector: api.L7Rules{
   638  				HTTP: []api.PortRuleHTTP{{Path: "/public", Method: "GET"}},
   639  			},
   640  			cachedFooSelector: api.L7Rules{
   641  				HTTP: []api.PortRuleHTTP{{Path: "/private", Method: "GET"}},
   642  			},
   643  		},
   644  		Ingress:          false,
   645  		DerivedFromRules: labels.LabelArrayList{nil, nil, nil},
   646  	}}
   647  
   648  	state := traceState{}
   649  	res, err := rule1.resolveEgressPolicy(fromBar, &state, L4PolicyMap{}, nil, testSelectorCache)
   650  	c.Assert(err, IsNil)
   651  	c.Assert(res, Not(IsNil))
   652  	c.Assert(res, checker.Equals, expected)
   653  	c.Assert(state.selectedRules, Equals, 1)
   654  	c.Assert(state.matchedRules, Equals, 0)
   655  	res.Detach(testSelectorCache)
   656  	expected.Detach(testSelectorCache)
   657  
   658  	state = traceState{}
   659  	res, err = rule1.resolveEgressPolicy(fromFoo, &state, L4PolicyMap{}, nil, testSelectorCache)
   660  	c.Assert(err, IsNil)
   661  	c.Assert(res, IsNil)
   662  	c.Assert(state.selectedRules, Equals, 0)
   663  	c.Assert(state.matchedRules, Equals, 0)
   664  
   665  	rule2 := &rule{
   666  		Rule: api.Rule{
   667  			EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
   668  			Egress: []api.EgressRule{
   669  				{
   670  					ToPorts: []api.PortRule{{
   671  						Ports: []api.PortProtocol{
   672  							{Port: "80", Protocol: api.ProtoTCP},
   673  						},
   674  					}},
   675  				},
   676  				{
   677  					ToPorts: []api.PortRule{{
   678  						Ports: []api.PortProtocol{
   679  							{Port: "80", Protocol: api.ProtoTCP},
   680  						},
   681  						Rules: &api.L7Rules{
   682  							Kafka: []api.PortRuleKafka{
   683  								{Topic: "foo"},
   684  							},
   685  						},
   686  					}},
   687  				},
   688  				{
   689  					ToEndpoints: fooSelector,
   690  					ToPorts: []api.PortRule{{
   691  						Ports: []api.PortProtocol{
   692  							{Port: "80", Protocol: api.ProtoTCP},
   693  						},
   694  						Rules: &api.L7Rules{
   695  							Kafka: []api.PortRuleKafka{
   696  								{Topic: "foo"},
   697  							},
   698  						},
   699  					}},
   700  				},
   701  			},
   702  		},
   703  	}
   704  
   705  	expected = L4PolicyMap{"80/TCP": &L4Filter{
   706  		Port: 80, Protocol: api.ProtoTCP, U8Proto: 6,
   707  		allowsAllAtL3:   true,
   708  		CachedSelectors: CachedSelectorSlice{wildcardCachedSelector, cachedFooSelector},
   709  		L7Parser:        ParserTypeKafka,
   710  		L7RulesPerEp: L7DataMap{
   711  			wildcardCachedSelector: api.L7Rules{
   712  				Kafka: []api.PortRuleKafka{{Topic: "foo"}},
   713  			},
   714  			cachedFooSelector: api.L7Rules{
   715  				Kafka: []api.PortRuleKafka{{Topic: "foo"}},
   716  			},
   717  		},
   718  		Ingress:          false,
   719  		DerivedFromRules: labels.LabelArrayList{nil, nil, nil},
   720  	}}
   721  
   722  	state = traceState{}
   723  	res, err = rule2.resolveEgressPolicy(fromBar, &state, L4PolicyMap{}, nil, testSelectorCache)
   724  	c.Assert(err, IsNil)
   725  	c.Assert(res, Not(IsNil))
   726  	c.Assert(res, checker.Equals, expected)
   727  	c.Assert(state.selectedRules, Equals, 1)
   728  	c.Assert(state.matchedRules, Equals, 0)
   729  	res.Detach(testSelectorCache)
   730  	expected.Detach(testSelectorCache)
   731  
   732  	state = traceState{}
   733  	res, err = rule2.resolveEgressPolicy(fromFoo, &state, L4PolicyMap{}, nil, testSelectorCache)
   734  	c.Assert(err, IsNil)
   735  	c.Assert(res, IsNil)
   736  	c.Assert(state.selectedRules, Equals, 0)
   737  	c.Assert(state.matchedRules, Equals, 0)
   738  
   739  	// Resolve rule1's policy, then try to add rule2.
   740  	res, err = rule1.resolveEgressPolicy(fromBar, &state, L4PolicyMap{}, nil, testSelectorCache)
   741  	c.Assert(err, IsNil)
   742  	c.Assert(res, Not(IsNil))
   743  	res.Detach(testSelectorCache)
   744  
   745  	// Similar to 'rule2', but with different topics for the l3-dependent
   746  	// rule and the l4-only rule.
   747  	rule3 := &rule{
   748  		Rule: api.Rule{
   749  			EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
   750  			Egress: []api.EgressRule{
   751  				{
   752  					ToEndpoints: fooSelector,
   753  					ToPorts: []api.PortRule{{
   754  						Ports: []api.PortProtocol{
   755  							{Port: "80", Protocol: api.ProtoTCP},
   756  						},
   757  						Rules: &api.L7Rules{
   758  							Kafka: []api.PortRuleKafka{
   759  								{Topic: "foo"},
   760  							},
   761  						},
   762  					}},
   763  				},
   764  				{
   765  					ToPorts: []api.PortRule{{
   766  						Ports: []api.PortProtocol{
   767  							{Port: "80", Protocol: api.ProtoTCP},
   768  						},
   769  						Rules: &api.L7Rules{
   770  							Kafka: []api.PortRuleKafka{
   771  								{Topic: "bar"},
   772  							},
   773  						},
   774  					}},
   775  				},
   776  			},
   777  		},
   778  	}
   779  
   780  	fooRules := api.L7Rules{
   781  		Kafka: []api.PortRuleKafka{{Topic: "foo"}},
   782  	}
   783  	barRules := api.L7Rules{
   784  		Kafka: []api.PortRuleKafka{{Topic: "bar"}},
   785  	}
   786  
   787  	// The l3-dependent l7 rules are not merged together.
   788  	l7map := L7DataMap{
   789  		cachedFooSelector:      fooRules,
   790  		wildcardCachedSelector: barRules,
   791  	}
   792  	expected = L4PolicyMap{"80/TCP": &L4Filter{
   793  		Port: 80, Protocol: api.ProtoTCP, U8Proto: 6,
   794  		allowsAllAtL3:   true,
   795  		CachedSelectors: CachedSelectorSlice{cachedFooSelector, wildcardCachedSelector},
   796  		L7Parser:        "kafka", L7RulesPerEp: l7map, Ingress: false,
   797  		DerivedFromRules: labels.LabelArrayList{nil, nil},
   798  	}}
   799  
   800  	state = traceState{}
   801  	res, err = rule3.resolveEgressPolicy(fromBar, &state, L4PolicyMap{}, nil, testSelectorCache)
   802  	c.Assert(err, IsNil)
   803  	c.Assert(res, Not(IsNil))
   804  	c.Assert(res, checker.Equals, expected)
   805  	c.Assert(state.selectedRules, Equals, 1)
   806  	c.Assert(state.matchedRules, Equals, 0)
   807  	res.Detach(testSelectorCache)
   808  	expected.Detach(testSelectorCache)
   809  }
   810  
   811  func (ds *PolicyTestSuite) TestRuleWithNoEndpointSelector(c *C) {
   812  	apiRule1 := api.Rule{
   813  		Ingress: []api.IngressRule{
   814  			{
   815  				FromCIDR: []api.CIDR{
   816  					"10.0.1.0/24",
   817  					"192.168.2.0",
   818  					"10.0.3.1",
   819  					"2001:db8::1/48",
   820  					"2001:db9::",
   821  				},
   822  			},
   823  		},
   824  		Egress: []api.EgressRule{
   825  			{
   826  				ToCIDR: []api.CIDR{
   827  					"10.1.0.0/16",
   828  					"2001:dbf::/64",
   829  				},
   830  			}, {
   831  				ToCIDRSet: []api.CIDRRule{{Cidr: api.CIDR("10.0.0.0/8"), ExceptCIDRs: []api.CIDR{"10.96.0.0/12"}}},
   832  			},
   833  		},
   834  	}
   835  
   836  	err := apiRule1.Sanitize()
   837  	c.Assert(err, Not(IsNil))
   838  }
   839  
   840  func (ds *PolicyTestSuite) TestL3Policy(c *C) {
   841  	apiRule1 := api.Rule{
   842  		EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
   843  
   844  		Ingress: []api.IngressRule{
   845  			{
   846  				FromCIDR: []api.CIDR{
   847  					"10.0.1.0/24",
   848  					"192.168.2.0",
   849  					"10.0.3.1",
   850  					"2001:db8::1/48",
   851  					"2001:db9::",
   852  				},
   853  			},
   854  		},
   855  		Egress: []api.EgressRule{
   856  			{
   857  				ToCIDR: []api.CIDR{
   858  					"10.1.0.0/16",
   859  					"2001:dbf::/64",
   860  				},
   861  			}, {
   862  				ToCIDRSet: []api.CIDRRule{{Cidr: api.CIDR("10.0.0.0/8"), ExceptCIDRs: []api.CIDR{"10.96.0.0/12"}}},
   863  			},
   864  		},
   865  	}
   866  
   867  	err := apiRule1.Sanitize()
   868  	c.Assert(err, IsNil)
   869  
   870  	rule1 := &rule{Rule: apiRule1}
   871  	err = rule1.Sanitize()
   872  	c.Assert(err, IsNil)
   873  
   874  	expected := NewCIDRPolicy()
   875  	expected.Ingress.Map["10.0.1.0/24"] = &CIDRPolicyMapRule{Prefix: net.IPNet{IP: []byte{10, 0, 1, 0}, Mask: []byte{255, 255, 255, 0}}, DerivedFromRules: labels.LabelArrayList{nil}}
   876  	expected.Ingress.Map["192.168.2.0/24"] = &CIDRPolicyMapRule{Prefix: net.IPNet{IP: []byte{192, 168, 2, 0}, Mask: []byte{255, 255, 255, 0}}, DerivedFromRules: labels.LabelArrayList{nil}}
   877  	expected.Ingress.Map["10.0.3.1/32"] = &CIDRPolicyMapRule{Prefix: net.IPNet{IP: []byte{10, 0, 3, 1}, Mask: []byte{255, 255, 255, 255}}, DerivedFromRules: labels.LabelArrayList{nil}}
   878  	expected.Ingress.IPv4PrefixCount[32] = 1
   879  	expected.Ingress.IPv4PrefixCount[24] = 2
   880  	expected.Ingress.Map["2001:db8::/48"] = &CIDRPolicyMapRule{Prefix: net.IPNet{IP: []byte{0x20, 1, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Mask: []byte{255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}}, DerivedFromRules: labels.LabelArrayList{nil}}
   881  	expected.Ingress.Map["2001:db9::/128"] = &CIDRPolicyMapRule{Prefix: net.IPNet{IP: []byte{0x20, 1, 0xd, 0xb9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}}, DerivedFromRules: labels.LabelArrayList{nil}}
   882  	expected.Ingress.IPv6PrefixCount[128] = 1
   883  	expected.Ingress.IPv6PrefixCount[48] = 1
   884  	expected.Egress.Map["10.1.0.0/16"] = &CIDRPolicyMapRule{Prefix: net.IPNet{IP: []byte{10, 1, 0, 0}, Mask: []byte{255, 255, 0, 0}}, DerivedFromRules: labels.LabelArrayList{nil}}
   885  	expected.Egress.Map["10.128.0.0/9"] = &CIDRPolicyMapRule{Prefix: net.IPNet{IP: []byte{10, 128, 0, 0}, Mask: []byte{255, 128, 0, 0}}, DerivedFromRules: labels.LabelArrayList{nil}}
   886  	expected.Egress.Map["10.0.0.0/10"] = &CIDRPolicyMapRule{Prefix: net.IPNet{IP: []byte{10, 0, 0, 0}, Mask: []byte{255, 192, 0, 0}}, DerivedFromRules: labels.LabelArrayList{nil}}
   887  	expected.Egress.Map["10.64.0.0/11"] = &CIDRPolicyMapRule{Prefix: net.IPNet{IP: []byte{10, 64, 0, 0}, Mask: []byte{255, 224, 0, 0}}, DerivedFromRules: labels.LabelArrayList{nil}}
   888  	expected.Egress.Map["10.112.0.0/12"] = &CIDRPolicyMapRule{Prefix: net.IPNet{IP: []byte{10, 112, 0, 0}, Mask: []byte{255, 240, 0, 0}}, DerivedFromRules: labels.LabelArrayList{nil}}
   889  	expected.Egress.IPv4PrefixCount[16] = 1
   890  	expected.Egress.IPv4PrefixCount[12] = 1
   891  	expected.Egress.IPv4PrefixCount[11] = 1
   892  	expected.Egress.IPv4PrefixCount[10] = 1
   893  	expected.Egress.IPv4PrefixCount[9] = 1
   894  	expected.Egress.Map["2001:dbf::/64"] = &CIDRPolicyMapRule{Prefix: net.IPNet{IP: []byte{0x20, 1, 0xd, 0xbf, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, Mask: []byte{255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0, 0, 0, 0, 0}}, DerivedFromRules: labels.LabelArrayList{nil}}
   895  	expected.Egress.IPv6PrefixCount[64] = 1
   896  
   897  	toBar := &SearchContext{To: labels.ParseSelectLabelArray("bar")}
   898  	state := traceState{}
   899  	res := rule1.resolveCIDRPolicy(toBar, &state, NewCIDRPolicy())
   900  	c.Assert(res, Not(IsNil))
   901  	c.Assert(*res, checker.DeepEquals, *expected)
   902  	c.Assert(state.selectedRules, Equals, 1)
   903  	c.Assert(state.matchedRules, Equals, 0)
   904  
   905  	// Must be parsable, make sure Validate fails when not.
   906  	err = api.Rule{
   907  		EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
   908  		Ingress: []api.IngressRule{{
   909  			FromCIDR: []api.CIDR{"10.0.1..0/24"},
   910  		}},
   911  	}.Sanitize()
   912  	c.Assert(err, Not(IsNil))
   913  
   914  	// Test CIDRRule with no provided CIDR or ExceptionCIDR.
   915  	// Should fail as CIDR is required.
   916  	err = api.Rule{
   917  		EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
   918  		Ingress: []api.IngressRule{{
   919  			FromCIDRSet: []api.CIDRRule{{Cidr: "", ExceptCIDRs: nil}},
   920  		}},
   921  	}.Sanitize()
   922  	c.Assert(err, Not(IsNil))
   923  
   924  	// Test CIDRRule with only CIDR provided; should not fail, as ExceptionCIDR
   925  	// is optional.
   926  	err = api.Rule{
   927  		EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
   928  		Ingress: []api.IngressRule{{
   929  			FromCIDRSet: []api.CIDRRule{{Cidr: "10.0.1.0/24", ExceptCIDRs: nil}},
   930  		}},
   931  	}.Sanitize()
   932  	c.Assert(err, IsNil)
   933  
   934  	// Cannot provide just an IP to a CIDRRule; Cidr must be of format
   935  	// <IP>/<prefix>.
   936  	err = api.Rule{
   937  		EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
   938  		Ingress: []api.IngressRule{{
   939  			FromCIDRSet: []api.CIDRRule{{Cidr: "10.0.1.32", ExceptCIDRs: nil}},
   940  		}},
   941  	}.Sanitize()
   942  	c.Assert(err, Not(IsNil))
   943  
   944  	// Cannot exclude a range that is not part of the CIDR.
   945  	err = api.Rule{
   946  		EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
   947  		Ingress: []api.IngressRule{{
   948  			FromCIDRSet: []api.CIDRRule{{Cidr: "10.0.0.0/10", ExceptCIDRs: []api.CIDR{"10.64.0.0/11"}}},
   949  		}},
   950  	}.Sanitize()
   951  	c.Assert(err, Not(IsNil))
   952  
   953  	// Must have a contiguous mask, make sure Validate fails when not.
   954  	err = api.Rule{
   955  		EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
   956  		Ingress: []api.IngressRule{{
   957  			FromCIDR: []api.CIDR{"10.0.1.0/128.0.0.128"},
   958  		}},
   959  	}.Sanitize()
   960  	c.Assert(err, Not(IsNil))
   961  
   962  	// Prefix length must be in range for the address, make sure
   963  	// Validate fails if given prefix length is out of range.
   964  	err = api.Rule{
   965  		EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
   966  		Ingress: []api.IngressRule{{
   967  			FromCIDR: []api.CIDR{"10.0.1.0/34"},
   968  		}},
   969  	}.Sanitize()
   970  	c.Assert(err, Not(IsNil))
   971  }
   972  
   973  func (ds *PolicyTestSuite) TestL3PolicyRestrictions(c *C) {
   974  	// Check rejection of too many prefix lengths
   975  	cidrs := []api.CIDR{}
   976  	for i := 1; i < 42; i++ {
   977  		cidrs = append(cidrs, api.CIDR(fmt.Sprintf("%d::/%d", i, i)))
   978  	}
   979  	apiRule2 := api.Rule{
   980  		EndpointSelector: barSelector,
   981  		Ingress:          []api.IngressRule{{FromCIDR: cidrs}},
   982  	}
   983  	err := apiRule2.Sanitize()
   984  	c.Assert(err, Not(IsNil))
   985  	apiRule3 := api.Rule{
   986  		EndpointSelector: barSelector,
   987  		Egress:           []api.EgressRule{{ToCIDR: cidrs}},
   988  	}
   989  	err = apiRule3.Sanitize()
   990  	c.Assert(err, Not(IsNil))
   991  }
   992  
   993  // Tests the restrictions of combining certain label-based L3 and L4 policies.
   994  // This ensures that the user is informed of policy combinations that are not
   995  // implemented in the datapath.
   996  func (ds *PolicyTestSuite) TestEgressRuleRestrictions(c *C) {
   997  
   998  	fooSelector := []api.EndpointSelector{
   999  		api.NewESFromLabels(labels.ParseSelectLabel("foo")),
  1000  	}
  1001  
  1002  	// Cannot combine ToEndpoints and ToCIDR
  1003  	apiRule1 := api.Rule{
  1004  		EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
  1005  		Egress: []api.EgressRule{
  1006  			{
  1007  				ToCIDR: []api.CIDR{
  1008  					"10.1.0.0/16",
  1009  					"2001:dbf::/64",
  1010  				},
  1011  				ToEndpoints: fooSelector,
  1012  			},
  1013  		},
  1014  	}
  1015  
  1016  	err := apiRule1.Sanitize()
  1017  	c.Assert(err, Not(IsNil))
  1018  }
  1019  
  1020  func (ds *PolicyTestSuite) TestPolicyEntityValidationEgress(c *C) {
  1021  	r := api.Rule{
  1022  		EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
  1023  		Egress: []api.EgressRule{
  1024  			{
  1025  				ToEntities: []api.Entity{api.EntityWorld},
  1026  			},
  1027  		},
  1028  	}
  1029  	c.Assert(r.Sanitize(), IsNil)
  1030  	c.Assert(len(r.Egress[0].ToEntities), Equals, 1)
  1031  
  1032  	r.Egress[0].ToEntities = []api.Entity{api.EntityHost}
  1033  	c.Assert(r.Sanitize(), IsNil)
  1034  	c.Assert(len(r.Egress[0].ToEntities), Equals, 1)
  1035  
  1036  	r.Egress[0].ToEntities = []api.Entity{"trololo"}
  1037  	c.Assert(r.Sanitize(), NotNil)
  1038  }
  1039  
  1040  func (ds *PolicyTestSuite) TestPolicyEntityValidationIngress(c *C) {
  1041  	r := api.Rule{
  1042  		EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
  1043  		Ingress: []api.IngressRule{
  1044  			{
  1045  				FromEntities: []api.Entity{api.EntityWorld},
  1046  			},
  1047  		},
  1048  	}
  1049  	c.Assert(r.Sanitize(), IsNil)
  1050  	c.Assert(len(r.Ingress[0].FromEntities), Equals, 1)
  1051  
  1052  	r.Ingress[0].FromEntities = []api.Entity{api.EntityHost}
  1053  	c.Assert(r.Sanitize(), IsNil)
  1054  	c.Assert(len(r.Ingress[0].FromEntities), Equals, 1)
  1055  
  1056  	r.Ingress[0].FromEntities = []api.Entity{"trololo"}
  1057  	c.Assert(r.Sanitize(), NotNil)
  1058  }
  1059  
  1060  func (ds *PolicyTestSuite) TestPolicyEntityValidationEntitySelectorsFill(c *C) {
  1061  	r := api.Rule{
  1062  		EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
  1063  		Ingress: []api.IngressRule{
  1064  			{
  1065  				FromEntities: []api.Entity{api.EntityWorld, api.EntityHost},
  1066  			},
  1067  		},
  1068  		Egress: []api.EgressRule{
  1069  			{
  1070  				ToEntities: []api.Entity{api.EntityWorld, api.EntityHost},
  1071  			},
  1072  		},
  1073  	}
  1074  	c.Assert(r.Sanitize(), IsNil)
  1075  	c.Assert(len(r.Ingress[0].FromEntities), Equals, 2)
  1076  	c.Assert(len(r.Egress[0].ToEntities), Equals, 2)
  1077  }
  1078  
  1079  func (ds *PolicyTestSuite) TestL3RuleLabels(c *C) {
  1080  	ruleLabels := map[string]labels.LabelArray{
  1081  		"rule0": labels.ParseLabelArray("name=apiRule0"),
  1082  		"rule1": labels.ParseLabelArray("name=apiRule1"),
  1083  		"rule2": labels.ParseLabelArray("name=apiRule2"),
  1084  	}
  1085  
  1086  	rules := map[string]api.Rule{
  1087  		"rule0": {
  1088  			EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
  1089  			Labels:           ruleLabels["rule0"],
  1090  			Ingress:          []api.IngressRule{},
  1091  			Egress:           []api.EgressRule{},
  1092  		},
  1093  		"rule1": {
  1094  			EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
  1095  			Labels:           ruleLabels["rule1"],
  1096  			Ingress: []api.IngressRule{
  1097  				{
  1098  					FromCIDR: []api.CIDR{"10.0.1.0/32"},
  1099  				},
  1100  			},
  1101  			Egress: []api.EgressRule{
  1102  				{
  1103  					ToCIDR: []api.CIDR{"10.1.0.0/32"},
  1104  				},
  1105  			},
  1106  		},
  1107  		"rule2": {
  1108  			EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
  1109  			Labels:           ruleLabels["rule2"],
  1110  			Ingress: []api.IngressRule{
  1111  				{
  1112  					FromCIDR: []api.CIDR{"10.0.2.0/32"},
  1113  				},
  1114  			},
  1115  			Egress: []api.EgressRule{
  1116  				{
  1117  					ToCIDR: []api.CIDR{"10.2.0.0/32"},
  1118  				},
  1119  			},
  1120  		},
  1121  	}
  1122  
  1123  	testCases := []struct {
  1124  		description           string                           // the description to print in asserts
  1125  		rulesToApply          []string                         // the rules from the rules map to resolve, in order
  1126  		expectedIngressLabels map[string]labels.LabelArrayList // the slice of LabelArray we should see, per CIDR prefix
  1127  		expectedEgressLabels  map[string]labels.LabelArrayList // the slice of LabelArray we should see, per CIDR prefix
  1128  
  1129  	}{
  1130  		{
  1131  			description:           "Empty rule that matches. Should not apply labels",
  1132  			rulesToApply:          []string{"rule0"},
  1133  			expectedIngressLabels: nil,
  1134  			expectedEgressLabels:  nil,
  1135  		},
  1136  		{
  1137  			description:           "A rule that matches. Should apply labels",
  1138  			rulesToApply:          []string{"rule1"},
  1139  			expectedIngressLabels: map[string]labels.LabelArrayList{"10.0.1.0/32": {ruleLabels["rule1"]}},
  1140  			expectedEgressLabels:  map[string]labels.LabelArrayList{"10.1.0.0/32": {ruleLabels["rule1"]}},
  1141  		}, {
  1142  			description:  "Multiple matching rules. Should apply labels from all that have rule entries",
  1143  			rulesToApply: []string{"rule0", "rule1", "rule2"},
  1144  			expectedIngressLabels: map[string]labels.LabelArrayList{
  1145  				"10.0.1.0/32": {ruleLabels["rule1"]},
  1146  				"10.0.2.0/32": {ruleLabels["rule2"]}},
  1147  			expectedEgressLabels: map[string]labels.LabelArrayList{
  1148  				"10.1.0.0/32": {ruleLabels["rule1"]},
  1149  				"10.2.0.0/32": {ruleLabels["rule2"]}},
  1150  		}}
  1151  
  1152  	// endpoint selector for all tests
  1153  	toBar := &SearchContext{To: labels.ParseSelectLabelArray("bar")}
  1154  
  1155  	for _, test := range testCases {
  1156  		finalPolicy := NewCIDRPolicy()
  1157  		for _, r := range test.rulesToApply {
  1158  			apiRule := rules[r]
  1159  			err := apiRule.Sanitize()
  1160  			c.Assert(err, IsNil, Commentf("Cannot sanitize Rule: %+v", apiRule))
  1161  
  1162  			rule := &rule{Rule: apiRule}
  1163  
  1164  			rule.resolveCIDRPolicy(toBar, &traceState{}, finalPolicy)
  1165  		}
  1166  
  1167  		c.Assert(len(finalPolicy.Ingress.Map), Equals, len(test.expectedIngressLabels), Commentf(test.description))
  1168  		for cidrKey := range test.expectedIngressLabels {
  1169  			out := finalPolicy.Ingress.Map[cidrKey]
  1170  			c.Assert(out, Not(IsNil), Commentf(test.description))
  1171  			c.Assert(out.DerivedFromRules, checker.DeepEquals, test.expectedIngressLabels[cidrKey], Commentf(test.description))
  1172  		}
  1173  
  1174  		c.Assert(len(finalPolicy.Egress.Map), Equals, len(test.expectedEgressLabels), Commentf(test.description))
  1175  		for cidrKey := range test.expectedEgressLabels {
  1176  			out := finalPolicy.Egress.Map[cidrKey]
  1177  			c.Assert(out, Not(IsNil), Commentf(test.description))
  1178  			c.Assert(out.DerivedFromRules, checker.DeepEquals, test.expectedEgressLabels[cidrKey], Commentf(test.description))
  1179  		}
  1180  	}
  1181  }
  1182  
  1183  func (ds *PolicyTestSuite) TestL4RuleLabels(c *C) {
  1184  	ruleLabels := map[string]labels.LabelArray{
  1185  		"rule0": labels.ParseLabelArray("name=apiRule0"),
  1186  		"rule1": labels.ParseLabelArray("name=apiRule1"),
  1187  		"rule2": labels.ParseLabelArray("name=apiRule2"),
  1188  	}
  1189  
  1190  	rules := map[string]api.Rule{
  1191  		"rule0": {
  1192  			EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
  1193  			Labels:           ruleLabels["rule0"],
  1194  			Ingress:          []api.IngressRule{},
  1195  			Egress:           []api.EgressRule{},
  1196  		},
  1197  
  1198  		"rule1": {
  1199  			EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
  1200  			Labels:           ruleLabels["rule1"],
  1201  			Ingress: []api.IngressRule{
  1202  				{
  1203  					ToPorts: []api.PortRule{{
  1204  						Ports: []api.PortProtocol{{Port: "1010", Protocol: api.ProtoTCP}},
  1205  					}},
  1206  				},
  1207  			},
  1208  			Egress: []api.EgressRule{
  1209  				{
  1210  					ToPorts: []api.PortRule{{
  1211  						Ports: []api.PortProtocol{{Port: "1100", Protocol: api.ProtoTCP}},
  1212  					}},
  1213  				},
  1214  			},
  1215  		},
  1216  		"rule2": {
  1217  			EndpointSelector: api.NewESFromLabels(labels.ParseSelectLabel("bar")),
  1218  			Labels:           ruleLabels["rule2"],
  1219  			Ingress: []api.IngressRule{
  1220  				{
  1221  					ToPorts: []api.PortRule{{
  1222  						Ports: []api.PortProtocol{{Port: "1020", Protocol: api.ProtoTCP}},
  1223  					}},
  1224  				},
  1225  			},
  1226  			Egress: []api.EgressRule{
  1227  				{
  1228  					ToPorts: []api.PortRule{{
  1229  						Ports: []api.PortProtocol{{Port: "1200", Protocol: api.ProtoTCP}},
  1230  					}},
  1231  				},
  1232  			},
  1233  		},
  1234  	}
  1235  
  1236  	testCases := []struct {
  1237  		description           string                           // the description to print in asserts
  1238  		rulesToApply          []string                         // the rules from the rules map to resolve, in order
  1239  		expectedIngressLabels map[string]labels.LabelArrayList // the slice of LabelArray we should see, in order
  1240  		expectedEgressLabels  map[string]labels.LabelArrayList // the slice of LabelArray we should see, in order
  1241  
  1242  	}{
  1243  		{
  1244  			description:           "Empty rule that matches. Should not apply labels",
  1245  			rulesToApply:          []string{"rule0"},
  1246  			expectedIngressLabels: map[string]labels.LabelArrayList{},
  1247  			expectedEgressLabels:  map[string]labels.LabelArrayList{},
  1248  		},
  1249  		{
  1250  			description:           "A rule that matches. Should apply labels",
  1251  			rulesToApply:          []string{"rule1"},
  1252  			expectedIngressLabels: map[string]labels.LabelArrayList{"1010/TCP": {ruleLabels["rule1"]}},
  1253  			expectedEgressLabels:  map[string]labels.LabelArrayList{"1100/TCP": {ruleLabels["rule1"]}},
  1254  		}, {
  1255  			description:  "Multiple matching rules. Should apply labels from all that have rule entries",
  1256  			rulesToApply: []string{"rule0", "rule1", "rule2"},
  1257  			expectedIngressLabels: map[string]labels.LabelArrayList{
  1258  				"1010/TCP": {ruleLabels["rule1"]},
  1259  				"1020/TCP": {ruleLabels["rule2"]}},
  1260  			expectedEgressLabels: map[string]labels.LabelArrayList{
  1261  				"1100/TCP": {ruleLabels["rule1"]},
  1262  				"1200/TCP": {ruleLabels["rule2"]}},
  1263  		}}
  1264  
  1265  	// endpoint selector for all tests
  1266  	toBar := &SearchContext{To: labels.ParseSelectLabelArray("bar")}
  1267  	fromBar := &SearchContext{From: labels.ParseSelectLabelArray("bar")}
  1268  
  1269  	for _, test := range testCases {
  1270  		finalPolicy := NewL4Policy(0)
  1271  		for _, r := range test.rulesToApply {
  1272  			apiRule := rules[r]
  1273  			err := apiRule.Sanitize()
  1274  			c.Assert(err, IsNil, Commentf("Cannot sanitize api.Rule: %+v", apiRule))
  1275  
  1276  			rule := &rule{Rule: apiRule}
  1277  
  1278  			rule.resolveIngressPolicy(toBar, &traceState{}, finalPolicy.Ingress, nil, testSelectorCache)
  1279  			rule.resolveEgressPolicy(fromBar, &traceState{}, finalPolicy.Egress, nil, testSelectorCache)
  1280  		}
  1281  
  1282  		c.Assert(len(finalPolicy.Ingress), Equals, len(test.expectedIngressLabels), Commentf(test.description))
  1283  		for portProto := range test.expectedIngressLabels {
  1284  			out, found := finalPolicy.Ingress[portProto]
  1285  			c.Assert(found, Equals, true, Commentf(test.description))
  1286  			c.Assert(out, NotNil, Commentf(test.description))
  1287  			c.Assert(out.DerivedFromRules, checker.DeepEquals, test.expectedIngressLabels[portProto], Commentf(test.description))
  1288  		}
  1289  
  1290  		c.Assert(len(finalPolicy.Egress), Equals, len(test.expectedEgressLabels), Commentf(test.description))
  1291  		for portProto := range test.expectedEgressLabels {
  1292  			out, found := finalPolicy.Egress[portProto]
  1293  			c.Assert(found, Equals, true, Commentf(test.description))
  1294  			c.Assert(out, Not(IsNil), Commentf(test.description))
  1295  			c.Assert(out.DerivedFromRules, checker.DeepEquals, test.expectedEgressLabels[portProto], Commentf(test.description))
  1296  		}
  1297  		finalPolicy.Detach(testSelectorCache)
  1298  	}
  1299  }
  1300  
  1301  var (
  1302  	labelsA = labels.LabelArray{
  1303  		labels.NewLabel("id", "a", labels.LabelSourceK8s),
  1304  	}
  1305  
  1306  	endpointSelectorA = api.NewESFromLabels(labels.ParseSelectLabel("id=a"))
  1307  
  1308  	labelsB = labels.LabelArray{
  1309  		labels.NewLabel("id1", "b", labels.LabelSourceK8s),
  1310  		labels.NewLabel("id2", "c", labels.LabelSourceK8s),
  1311  	}
  1312  
  1313  	labelsC = labels.LabelArray{
  1314  		labels.NewLabel("id", "c", labels.LabelSourceK8s),
  1315  	}
  1316  
  1317  	endpointSelectorC = api.NewESFromLabels(labels.ParseSelectLabel("id=c"))
  1318  
  1319  	ctxAToB = SearchContext{From: labelsA, To: labelsB, Trace: TRACE_VERBOSE}
  1320  	ctxAToC = SearchContext{From: labelsA, To: labelsC, Trace: TRACE_VERBOSE}
  1321  )
  1322  
  1323  func expectResult(c *C, expected, obtained api.Decision, buffer *bytes.Buffer) {
  1324  	if obtained != expected {
  1325  		c.Errorf("Unexpected result: obtained=%v, expected=%v", obtained, expected)
  1326  		c.Log(buffer)
  1327  	}
  1328  }
  1329  
  1330  func checkIngress(c *C, repo *Repository, ctx *SearchContext, verdict api.Decision) {
  1331  	repo.Mutex.RLock()
  1332  	defer repo.Mutex.RUnlock()
  1333  
  1334  	buffer := new(bytes.Buffer)
  1335  	ctx.Logging = logging.NewLogBackend(buffer, "", 0)
  1336  	expectResult(c, verdict, repo.AllowsIngressRLocked(ctx), buffer)
  1337  }
  1338  
  1339  func checkEgress(c *C, repo *Repository, ctx *SearchContext, verdict api.Decision) {
  1340  	repo.Mutex.RLock()
  1341  	defer repo.Mutex.RUnlock()
  1342  
  1343  	buffer := new(bytes.Buffer)
  1344  	ctx.Logging = logging.NewLogBackend(buffer, "", 0)
  1345  	expectResult(c, verdict, repo.AllowsEgressRLocked(ctx), buffer)
  1346  }
  1347  
  1348  func parseAndAddRules(c *C, rules api.Rules) *Repository {
  1349  	repo := NewPolicyRepository()
  1350  	repo.selectorCache = testSelectorCache
  1351  
  1352  	_, _ = repo.AddList(rules)
  1353  	return repo
  1354  }
  1355  
  1356  func (ds *PolicyTestSuite) TestIngressAllowAll(c *C) {
  1357  	repo := parseAndAddRules(c, api.Rules{
  1358  		&api.Rule{
  1359  			EndpointSelector: endpointSelectorC,
  1360  			Ingress: []api.IngressRule{
  1361  				{
  1362  					// Allow all L3&L4 ingress rule
  1363  					FromEndpoints: []api.EndpointSelector{
  1364  						api.WildcardEndpointSelector,
  1365  					},
  1366  				},
  1367  			},
  1368  		},
  1369  	})
  1370  
  1371  	checkIngress(c, repo, &ctxAToB, api.Denied)
  1372  	checkIngress(c, repo, &ctxAToC, api.Allowed)
  1373  
  1374  	ctxAToC80 := ctxAToC
  1375  	ctxAToC80.DPorts = []*models.Port{{Port: 80, Protocol: models.PortProtocolTCP}}
  1376  	checkIngress(c, repo, &ctxAToC80, api.Allowed)
  1377  
  1378  	ctxAToC90 := ctxAToC
  1379  	ctxAToC90.DPorts = []*models.Port{{Port: 90, Protocol: models.PortProtocolTCP}}
  1380  	checkIngress(c, repo, &ctxAToC90, api.Allowed)
  1381  }
  1382  
  1383  func (ds *PolicyTestSuite) TestIngressAllowAllL4Overlap(c *C) {
  1384  	repo := parseAndAddRules(c, api.Rules{
  1385  		&api.Rule{
  1386  			EndpointSelector: endpointSelectorC,
  1387  			Ingress: []api.IngressRule{
  1388  				{
  1389  					// Allow all L3&L4 ingress rule
  1390  					FromEndpoints: []api.EndpointSelector{
  1391  						api.WildcardEndpointSelector,
  1392  					},
  1393  				},
  1394  				{
  1395  					// This rule is a subset of the above
  1396  					// rule and should *NOT* restrict to
  1397  					// port 80 only
  1398  					ToPorts: []api.PortRule{{
  1399  						Ports: []api.PortProtocol{
  1400  							{Port: "80", Protocol: api.ProtoTCP},
  1401  						},
  1402  					}},
  1403  				},
  1404  			},
  1405  		},
  1406  	})
  1407  
  1408  	ctxAToC80 := ctxAToC
  1409  	ctxAToC80.DPorts = []*models.Port{{Port: 80, Protocol: models.PortProtocolTCP}}
  1410  	checkIngress(c, repo, &ctxAToC80, api.Allowed)
  1411  
  1412  	ctxAToC90 := ctxAToC
  1413  	ctxAToC90.DPorts = []*models.Port{{Port: 90, Protocol: models.PortProtocolTCP}}
  1414  	checkIngress(c, repo, &ctxAToC90, api.Allowed)
  1415  }
  1416  
  1417  func (ds *PolicyTestSuite) TestIngressL4AllowAll(c *C) {
  1418  	repo := parseAndAddRules(c, api.Rules{
  1419  		&api.Rule{
  1420  			EndpointSelector: endpointSelectorC,
  1421  			Ingress: []api.IngressRule{
  1422  				{
  1423  					ToPorts: []api.PortRule{{
  1424  						Ports: []api.PortProtocol{
  1425  							{Port: "80", Protocol: api.ProtoTCP},
  1426  						},
  1427  					}},
  1428  				},
  1429  			},
  1430  		},
  1431  	})
  1432  
  1433  	ctxAToC80 := ctxAToC
  1434  	ctxAToC80.DPorts = []*models.Port{{Port: 80, Protocol: models.PortProtocolTCP}}
  1435  	checkIngress(c, repo, &ctxAToC80, api.Allowed)
  1436  
  1437  	ctxAToC90 := ctxAToC
  1438  	ctxAToC90.DPorts = []*models.Port{{Port: 90, Protocol: models.PortProtocolTCP}}
  1439  	checkIngress(c, repo, &ctxAToC90, api.Denied)
  1440  
  1441  	l4IngressPolicy, err := repo.ResolveL4IngressPolicy(&ctxAToC80)
  1442  	c.Assert(err, IsNil)
  1443  
  1444  	filter, ok := l4IngressPolicy["80/TCP"]
  1445  	c.Assert(ok, Equals, true)
  1446  	c.Assert(filter.Port, Equals, 80)
  1447  	c.Assert(filter.Ingress, Equals, true)
  1448  
  1449  	c.Assert(len(filter.CachedSelectors), Equals, 1)
  1450  	c.Assert(filter.CachedSelectors[0], checker.Equals, wildcardCachedSelector)
  1451  	l4IngressPolicy.Detach(repo.GetSelectorCache())
  1452  }
  1453  
  1454  func (ds *PolicyTestSuite) TestEgressAllowAll(c *C) {
  1455  	repo := parseAndAddRules(c, api.Rules{
  1456  		&api.Rule{
  1457  			EndpointSelector: endpointSelectorA,
  1458  			Egress: []api.EgressRule{
  1459  				{
  1460  					ToEndpoints: []api.EndpointSelector{
  1461  						api.WildcardEndpointSelector,
  1462  					},
  1463  				},
  1464  			},
  1465  		},
  1466  	})
  1467  
  1468  	checkEgress(c, repo, &ctxAToB, api.Allowed)
  1469  	checkEgress(c, repo, &ctxAToC, api.Allowed)
  1470  
  1471  	ctxAToC80 := ctxAToC
  1472  	ctxAToC80.DPorts = []*models.Port{{Port: 80, Protocol: models.PortProtocolTCP}}
  1473  	checkEgress(c, repo, &ctxAToC80, api.Allowed)
  1474  
  1475  	ctxAToC90 := ctxAToC
  1476  	ctxAToC90.DPorts = []*models.Port{{Port: 90, Protocol: models.PortProtocolTCP}}
  1477  	checkEgress(c, repo, &ctxAToC90, api.Allowed)
  1478  }
  1479  
  1480  func (ds *PolicyTestSuite) TestEgressL4AllowAll(c *C) {
  1481  	repo := parseAndAddRules(c, api.Rules{
  1482  		&api.Rule{
  1483  			EndpointSelector: endpointSelectorA,
  1484  			Egress: []api.EgressRule{
  1485  				{
  1486  					ToPorts: []api.PortRule{{
  1487  						Ports: []api.PortProtocol{
  1488  							{Port: "80", Protocol: api.ProtoTCP},
  1489  						},
  1490  					}},
  1491  				},
  1492  			},
  1493  		},
  1494  	})
  1495  
  1496  	ctxAToC80 := ctxAToC
  1497  	ctxAToC80.DPorts = []*models.Port{{Port: 80, Protocol: models.PortProtocolTCP}}
  1498  	checkEgress(c, repo, &ctxAToC80, api.Allowed)
  1499  
  1500  	ctxAToC90 := ctxAToC
  1501  	ctxAToC90.DPorts = []*models.Port{{Port: 90, Protocol: models.PortProtocolTCP}}
  1502  	checkEgress(c, repo, &ctxAToC90, api.Denied)
  1503  
  1504  	buffer := new(bytes.Buffer)
  1505  	ctx := SearchContext{From: labelsA, Trace: TRACE_VERBOSE}
  1506  	ctx.Logging = logging.NewLogBackend(buffer, "", 0)
  1507  
  1508  	l4EgressPolicy, err := repo.ResolveL4EgressPolicy(&ctx)
  1509  	c.Assert(err, IsNil)
  1510  
  1511  	c.Log(buffer)
  1512  
  1513  	filter, ok := l4EgressPolicy["80/TCP"]
  1514  	c.Assert(ok, Equals, true)
  1515  	c.Assert(filter.Port, Equals, 80)
  1516  	c.Assert(filter.Ingress, Equals, false)
  1517  
  1518  	c.Assert(len(filter.CachedSelectors), Equals, 1)
  1519  	c.Assert(filter.CachedSelectors[0], checker.Equals, wildcardCachedSelector)
  1520  	l4EgressPolicy.Detach(repo.GetSelectorCache())
  1521  }
  1522  
  1523  func (ds *PolicyTestSuite) TestEgressL4AllowWorld(c *C) {
  1524  	repo := parseAndAddRules(c, api.Rules{
  1525  		&api.Rule{
  1526  			EndpointSelector: endpointSelectorA,
  1527  			Egress: []api.EgressRule{
  1528  				{
  1529  					ToEntities: []api.Entity{api.EntityWorld},
  1530  					ToPorts: []api.PortRule{{
  1531  						Ports: []api.PortProtocol{
  1532  							{Port: "80", Protocol: api.ProtoTCP},
  1533  						},
  1534  					}},
  1535  				},
  1536  			},
  1537  		},
  1538  	})
  1539  
  1540  	worldLabel := labels.ParseSelectLabelArray("reserved:world")
  1541  	ctxAToWorld80 := SearchContext{From: labelsA, To: worldLabel, Trace: TRACE_VERBOSE}
  1542  	ctxAToWorld80.DPorts = []*models.Port{{Port: 80, Protocol: models.PortProtocolTCP}}
  1543  	checkEgress(c, repo, &ctxAToWorld80, api.Allowed)
  1544  
  1545  	ctxAToWorld90 := ctxAToWorld80
  1546  	ctxAToWorld90.DPorts = []*models.Port{{Port: 90, Protocol: models.PortProtocolTCP}}
  1547  	checkEgress(c, repo, &ctxAToWorld90, api.Denied)
  1548  
  1549  	// Pod to pod must be denied on port 80 and 90, only world was whitelisted
  1550  	fooLabel := labels.ParseSelectLabelArray("k8s:app=foo")
  1551  	ctxAToFoo := SearchContext{From: labelsA, To: fooLabel, Trace: TRACE_VERBOSE,
  1552  		DPorts: []*models.Port{{Port: 80, Protocol: models.PortProtocolTCP}}}
  1553  	checkEgress(c, repo, &ctxAToFoo, api.Denied)
  1554  	ctxAToFoo90 := ctxAToFoo
  1555  	ctxAToFoo90.DPorts = []*models.Port{{Port: 90, Protocol: models.PortProtocolTCP}}
  1556  	checkEgress(c, repo, &ctxAToFoo90, api.Denied)
  1557  
  1558  	buffer := new(bytes.Buffer)
  1559  	ctx := SearchContext{From: labelsA, Trace: TRACE_VERBOSE}
  1560  	ctx.Logging = logging.NewLogBackend(buffer, "", 0)
  1561  
  1562  	l4EgressPolicy, err := repo.ResolveL4EgressPolicy(&ctx)
  1563  	c.Assert(err, IsNil)
  1564  
  1565  	c.Log(buffer)
  1566  
  1567  	filter, ok := l4EgressPolicy["80/TCP"]
  1568  	c.Assert(ok, Equals, true)
  1569  	c.Assert(filter.Port, Equals, 80)
  1570  	c.Assert(filter.Ingress, Equals, false)
  1571  
  1572  	c.Assert(len(filter.CachedSelectors), Equals, 1)
  1573  	l4EgressPolicy.Detach(repo.GetSelectorCache())
  1574  }
  1575  
  1576  func (ds *PolicyTestSuite) TestEgressL4AllowAllEntity(c *C) {
  1577  	repo := parseAndAddRules(c, api.Rules{
  1578  		&api.Rule{
  1579  			EndpointSelector: endpointSelectorA,
  1580  			Egress: []api.EgressRule{
  1581  				{
  1582  					ToEntities: []api.Entity{api.EntityAll},
  1583  					ToPorts: []api.PortRule{{
  1584  						Ports: []api.PortProtocol{
  1585  							{Port: "80", Protocol: api.ProtoTCP},
  1586  						},
  1587  					}},
  1588  				},
  1589  			},
  1590  		},
  1591  	})
  1592  
  1593  	worldLabel := labels.ParseSelectLabelArray("reserved:world")
  1594  	ctxAToWorld80 := SearchContext{From: labelsA, To: worldLabel, Trace: TRACE_VERBOSE}
  1595  	ctxAToWorld80.DPorts = []*models.Port{{Port: 80, Protocol: models.PortProtocolTCP}}
  1596  	checkEgress(c, repo, &ctxAToWorld80, api.Allowed)
  1597  
  1598  	ctxAToWorld90 := ctxAToWorld80
  1599  	ctxAToWorld90.DPorts = []*models.Port{{Port: 90, Protocol: models.PortProtocolTCP}}
  1600  	checkEgress(c, repo, &ctxAToWorld90, api.Denied)
  1601  
  1602  	// Pod to pod must be allowed on port 80, denied on port 90 (all identity)
  1603  	fooLabel := labels.ParseSelectLabelArray("k8s:app=foo")
  1604  	ctxAToFoo := SearchContext{From: labelsA, To: fooLabel, Trace: TRACE_VERBOSE,
  1605  		DPorts: []*models.Port{{Port: 80, Protocol: models.PortProtocolTCP}}}
  1606  	checkEgress(c, repo, &ctxAToFoo, api.Allowed)
  1607  	ctxAToFoo90 := ctxAToFoo
  1608  	ctxAToFoo90.DPorts = []*models.Port{{Port: 90, Protocol: models.PortProtocolTCP}}
  1609  	checkEgress(c, repo, &ctxAToFoo90, api.Denied)
  1610  
  1611  	buffer := new(bytes.Buffer)
  1612  	ctx := SearchContext{From: labelsA, Trace: TRACE_VERBOSE}
  1613  	ctx.Logging = logging.NewLogBackend(buffer, "", 0)
  1614  
  1615  	l4EgressPolicy, err := repo.ResolveL4EgressPolicy(&ctx)
  1616  	c.Assert(err, IsNil)
  1617  
  1618  	c.Log(buffer)
  1619  
  1620  	filter, ok := l4EgressPolicy["80/TCP"]
  1621  	c.Assert(ok, Equals, true)
  1622  	c.Assert(filter.Port, Equals, 80)
  1623  	c.Assert(filter.Ingress, Equals, false)
  1624  
  1625  	c.Assert(len(filter.CachedSelectors), Equals, 1)
  1626  	l4EgressPolicy.Detach(repo.GetSelectorCache())
  1627  }
  1628  
  1629  func (ds *PolicyTestSuite) TestEgressL3AllowWorld(c *C) {
  1630  	repo := parseAndAddRules(c, api.Rules{
  1631  		&api.Rule{
  1632  			EndpointSelector: endpointSelectorA,
  1633  			Egress: []api.EgressRule{
  1634  				{
  1635  					ToEntities: []api.Entity{api.EntityWorld},
  1636  				},
  1637  			},
  1638  		},
  1639  	})
  1640  
  1641  	worldLabel := labels.ParseSelectLabelArray("reserved:world")
  1642  	ctxAToWorld80 := SearchContext{From: labelsA, To: worldLabel, Trace: TRACE_VERBOSE}
  1643  	ctxAToWorld80.DPorts = []*models.Port{{Port: 80, Protocol: models.PortProtocolTCP}}
  1644  	checkEgress(c, repo, &ctxAToWorld80, api.Allowed)
  1645  
  1646  	ctxAToWorld90 := ctxAToWorld80
  1647  	ctxAToWorld90.DPorts = []*models.Port{{Port: 90, Protocol: models.PortProtocolTCP}}
  1648  	checkEgress(c, repo, &ctxAToWorld90, api.Allowed)
  1649  
  1650  	// Pod to pod must be denied on port 80 and 90, only world was whitelisted
  1651  	fooLabel := labels.ParseSelectLabelArray("k8s:app=foo")
  1652  	ctxAToFoo := SearchContext{From: labelsA, To: fooLabel, Trace: TRACE_VERBOSE,
  1653  		DPorts: []*models.Port{{Port: 80, Protocol: models.PortProtocolTCP}}}
  1654  	checkEgress(c, repo, &ctxAToFoo, api.Denied)
  1655  	ctxAToFoo90 := ctxAToFoo
  1656  	ctxAToFoo90.DPorts = []*models.Port{{Port: 90, Protocol: models.PortProtocolTCP}}
  1657  	checkEgress(c, repo, &ctxAToFoo90, api.Denied)
  1658  
  1659  	buffer := new(bytes.Buffer)
  1660  	ctx := SearchContext{From: labelsA, Trace: TRACE_VERBOSE}
  1661  	ctx.Logging = logging.NewLogBackend(buffer, "", 0)
  1662  }
  1663  
  1664  func (ds *PolicyTestSuite) TestEgressL3AllowAllEntity(c *C) {
  1665  	repo := parseAndAddRules(c, api.Rules{
  1666  		&api.Rule{
  1667  			EndpointSelector: endpointSelectorA,
  1668  			Egress: []api.EgressRule{
  1669  				{
  1670  					ToEntities: []api.Entity{api.EntityAll},
  1671  				},
  1672  			},
  1673  		},
  1674  	})
  1675  
  1676  	worldLabel := labels.ParseSelectLabelArray("reserved:world")
  1677  	ctxAToWorld80 := SearchContext{From: labelsA, To: worldLabel, Trace: TRACE_VERBOSE}
  1678  	ctxAToWorld80.DPorts = []*models.Port{{Port: 80, Protocol: models.PortProtocolTCP}}
  1679  	checkEgress(c, repo, &ctxAToWorld80, api.Allowed)
  1680  
  1681  	ctxAToWorld90 := ctxAToWorld80
  1682  	ctxAToWorld90.DPorts = []*models.Port{{Port: 90, Protocol: models.PortProtocolTCP}}
  1683  	checkEgress(c, repo, &ctxAToWorld90, api.Allowed)
  1684  
  1685  	// Pod to pod must be allowed on both port 80 and 90 (L3 only rule)
  1686  	fooLabel := labels.ParseSelectLabelArray("k8s:app=foo")
  1687  	ctxAToFoo := SearchContext{From: labelsA, To: fooLabel, Trace: TRACE_VERBOSE,
  1688  		DPorts: []*models.Port{{Port: 80, Protocol: models.PortProtocolTCP}}}
  1689  	checkEgress(c, repo, &ctxAToFoo, api.Allowed)
  1690  	ctxAToFoo90 := ctxAToFoo
  1691  	ctxAToFoo90.DPorts = []*models.Port{{Port: 90, Protocol: models.PortProtocolTCP}}
  1692  	checkEgress(c, repo, &ctxAToFoo90, api.Allowed)
  1693  
  1694  	buffer := new(bytes.Buffer)
  1695  	ctx := SearchContext{From: labelsA, Trace: TRACE_VERBOSE}
  1696  	ctx.Logging = logging.NewLogBackend(buffer, "", 0)
  1697  }
  1698  
  1699  func (ds *PolicyTestSuite) TestL4WildcardMerge(c *C) {
  1700  
  1701  	// First, test implicit case.
  1702  	//
  1703  	// Test the case where if we have rules that select the same endpoint on the
  1704  	// same port-protocol tuple with one that is L4-only, and the other applying
  1705  	// at L4 and L7, that the L4-only rule shadows the L4-L7 rule. This is because
  1706  	// L4-only rule implicitly allows all traffic at L7, so the L7-related
  1707  	// parts of the L4-L7 rule are useless.
  1708  	repo := parseAndAddRules(c, api.Rules{&api.Rule{
  1709  		EndpointSelector: endpointSelectorA,
  1710  		Ingress: []api.IngressRule{
  1711  			{
  1712  				FromEndpoints: []api.EndpointSelector{endpointSelectorC},
  1713  				ToPorts: []api.PortRule{{
  1714  					Ports: []api.PortProtocol{
  1715  						{Port: "80", Protocol: api.ProtoTCP},
  1716  					},
  1717  					Rules: &api.L7Rules{
  1718  						HTTP: []api.PortRuleHTTP{
  1719  							{Method: "GET", Path: "/"},
  1720  						},
  1721  					},
  1722  				}},
  1723  			},
  1724  			{
  1725  				ToPorts: []api.PortRule{{
  1726  					Ports: []api.PortProtocol{
  1727  						{Port: "80", Protocol: api.ProtoTCP},
  1728  					},
  1729  				}},
  1730  			},
  1731  		},
  1732  	}})
  1733  
  1734  	buffer := new(bytes.Buffer)
  1735  	ctx := SearchContext{To: labelsA, Trace: TRACE_VERBOSE}
  1736  	ctx.Logging = logging.NewLogBackend(buffer, "", 0)
  1737  
  1738  	l4IngressPolicy, err := repo.ResolveL4IngressPolicy(&ctx)
  1739  	c.Assert(err, IsNil)
  1740  
  1741  	c.Log(buffer)
  1742  
  1743  	filter, ok := l4IngressPolicy["80/TCP"]
  1744  	c.Assert(ok, Equals, true)
  1745  	c.Assert(filter.Port, Equals, 80)
  1746  	c.Assert(filter.Ingress, Equals, true)
  1747  
  1748  	c.Assert(len(filter.CachedSelectors), Equals, 2)
  1749  	c.Assert(filter.CachedSelectors[0], checker.Equals, cachedSelectorC)
  1750  	c.Assert(filter.CachedSelectors[1], checker.Equals, wildcardCachedSelector)
  1751  
  1752  	c.Assert(filter.L7Parser, Equals, ParserTypeHTTP)
  1753  	c.Assert(len(filter.L7RulesPerEp), Equals, 2)
  1754  	l4IngressPolicy.Detach(repo.GetSelectorCache())
  1755  
  1756  	// Test the reverse order as well; ensure that we check both conditions
  1757  	// for if L4-only policy is in the L4Filter for the same port-protocol tuple,
  1758  	// and L7 metadata exists in the L4Filter we are adding; expect to resolve
  1759  	// to L4-only policy without any L7-metadata.
  1760  	repo = parseAndAddRules(c, api.Rules{&api.Rule{
  1761  		EndpointSelector: endpointSelectorA,
  1762  		Ingress: []api.IngressRule{
  1763  			{
  1764  				ToPorts: []api.PortRule{{
  1765  					Ports: []api.PortProtocol{
  1766  						{Port: "80", Protocol: api.ProtoTCP},
  1767  					},
  1768  				}},
  1769  			},
  1770  			{
  1771  				FromEndpoints: []api.EndpointSelector{endpointSelectorC},
  1772  				ToPorts: []api.PortRule{{
  1773  					Ports: []api.PortProtocol{
  1774  						{Port: "80", Protocol: api.ProtoTCP},
  1775  					},
  1776  					Rules: &api.L7Rules{
  1777  						HTTP: []api.PortRuleHTTP{
  1778  							{Method: "GET", Path: "/"},
  1779  						},
  1780  					},
  1781  				}},
  1782  			},
  1783  		},
  1784  	}})
  1785  
  1786  	buffer = new(bytes.Buffer)
  1787  	ctx = SearchContext{To: labelsA, Trace: TRACE_VERBOSE}
  1788  	ctx.Logging = logging.NewLogBackend(buffer, "", 0)
  1789  
  1790  	l4IngressPolicy, err = repo.ResolveL4IngressPolicy(&ctx)
  1791  	c.Assert(err, IsNil)
  1792  
  1793  	c.Log(buffer)
  1794  
  1795  	filter, ok = l4IngressPolicy["80/TCP"]
  1796  	c.Assert(ok, Equals, true)
  1797  	c.Assert(filter.Port, Equals, 80)
  1798  	c.Assert(filter.Ingress, Equals, true)
  1799  
  1800  	c.Assert(len(filter.CachedSelectors), Equals, 2)
  1801  	c.Assert(filter.CachedSelectors[0], checker.Equals, wildcardCachedSelector)
  1802  	c.Assert(filter.CachedSelectors[1], checker.Equals, cachedSelectorC)
  1803  
  1804  	c.Assert(filter.L7Parser, Equals, ParserTypeHTTP)
  1805  	c.Assert(len(filter.L7RulesPerEp), Equals, 2)
  1806  	l4IngressPolicy.Detach(repo.GetSelectorCache())
  1807  
  1808  	// Second, test the explicit allow at L3.
  1809  	repo = parseAndAddRules(c, api.Rules{&api.Rule{
  1810  		EndpointSelector: endpointSelectorA,
  1811  		Ingress: []api.IngressRule{
  1812  			{
  1813  				FromEndpoints: []api.EndpointSelector{endpointSelectorC},
  1814  				ToPorts: []api.PortRule{{
  1815  					Ports: []api.PortProtocol{
  1816  						{Port: "80", Protocol: api.ProtoTCP},
  1817  					},
  1818  					Rules: &api.L7Rules{
  1819  						HTTP: []api.PortRuleHTTP{
  1820  							{Method: "GET", Path: "/"},
  1821  						},
  1822  					},
  1823  				}},
  1824  			},
  1825  			{
  1826  				FromEndpoints: []api.EndpointSelector{api.WildcardEndpointSelector},
  1827  				ToPorts: []api.PortRule{{
  1828  					Ports: []api.PortProtocol{
  1829  						{Port: "80", Protocol: api.ProtoTCP},
  1830  					},
  1831  				}},
  1832  			},
  1833  		},
  1834  	}})
  1835  
  1836  	buffer = new(bytes.Buffer)
  1837  	ctx = SearchContext{To: labelsA, Trace: TRACE_VERBOSE}
  1838  	ctx.Logging = logging.NewLogBackend(buffer, "", 0)
  1839  
  1840  	l4IngressPolicy, err = repo.ResolveL4IngressPolicy(&ctx)
  1841  	c.Assert(err, IsNil)
  1842  
  1843  	c.Log(buffer)
  1844  
  1845  	filter, ok = l4IngressPolicy["80/TCP"]
  1846  	c.Assert(ok, Equals, true)
  1847  	c.Assert(filter.Port, Equals, 80)
  1848  	c.Assert(filter.Ingress, Equals, true)
  1849  
  1850  	c.Assert(len(filter.CachedSelectors), Equals, 2)
  1851  	c.Assert(filter.L7Parser, Equals, ParserTypeHTTP)
  1852  	c.Assert(len(filter.L7RulesPerEp), Equals, 2)
  1853  	l4IngressPolicy.Detach(repo.GetSelectorCache())
  1854  
  1855  	// Test the reverse order as well; ensure that we check both conditions
  1856  	// for if L4-only policy is in the L4Filter for the same port-protocol tuple,
  1857  	// and L7 metadata exists in the L4Filter we are adding; expect to resolve
  1858  	// to L4-only policy without any L7-metadata.
  1859  	repo = parseAndAddRules(c, api.Rules{&api.Rule{
  1860  		EndpointSelector: endpointSelectorA,
  1861  		Ingress: []api.IngressRule{
  1862  			{
  1863  				FromEndpoints: []api.EndpointSelector{api.WildcardEndpointSelector},
  1864  				ToPorts: []api.PortRule{{
  1865  					Ports: []api.PortProtocol{
  1866  						{Port: "80", Protocol: api.ProtoTCP},
  1867  					},
  1868  				}},
  1869  			},
  1870  			{
  1871  				FromEndpoints: []api.EndpointSelector{endpointSelectorC},
  1872  				ToPorts: []api.PortRule{{
  1873  					Ports: []api.PortProtocol{
  1874  						{Port: "80", Protocol: api.ProtoTCP},
  1875  					},
  1876  					Rules: &api.L7Rules{
  1877  						HTTP: []api.PortRuleHTTP{
  1878  							{Method: "GET", Path: "/"},
  1879  						},
  1880  					},
  1881  				}},
  1882  			},
  1883  		},
  1884  	}})
  1885  
  1886  	buffer = new(bytes.Buffer)
  1887  	ctx = SearchContext{To: labelsA, Trace: TRACE_VERBOSE}
  1888  	ctx.Logging = logging.NewLogBackend(buffer, "", 0)
  1889  
  1890  	l4IngressPolicy, err = repo.ResolveL4IngressPolicy(&ctx)
  1891  	c.Assert(err, IsNil)
  1892  
  1893  	c.Log(buffer)
  1894  
  1895  	filter, ok = l4IngressPolicy["80/TCP"]
  1896  	c.Assert(ok, Equals, true)
  1897  	c.Assert(filter.Port, Equals, 80)
  1898  	c.Assert(filter.Ingress, Equals, true)
  1899  
  1900  	c.Assert(len(filter.CachedSelectors), Equals, 2)
  1901  
  1902  	c.Assert(filter.L7Parser, Equals, ParserTypeHTTP)
  1903  	c.Assert(len(filter.L7RulesPerEp), Equals, 2)
  1904  	l4IngressPolicy.Detach(repo.GetSelectorCache())
  1905  }
  1906  
  1907  func (ds *PolicyTestSuite) TestL3L4L7Merge(c *C) {
  1908  
  1909  	// First rule allows ingress from all endpoints to port 80 only on
  1910  	// GET to "/". However, second rule allows all traffic on port 80 only to a
  1911  	// specific endpoint. When these rules are merged, it equates to allowing
  1912  	// all traffic from port 80 from any endpoint.
  1913  	//
  1914  	// TODO: This comment can't be correct, the resulting policy
  1915  	// should allow all on port 80 only from endpoint C, traffic
  1916  	// from all other endpoints should still only allow only GET
  1917  	// on "/".
  1918  	repo := parseAndAddRules(c, api.Rules{&api.Rule{
  1919  		EndpointSelector: endpointSelectorA,
  1920  		Ingress: []api.IngressRule{
  1921  			{
  1922  				ToPorts: []api.PortRule{{
  1923  					Ports: []api.PortProtocol{
  1924  						{Port: "80", Protocol: api.ProtoTCP},
  1925  					},
  1926  					Rules: &api.L7Rules{
  1927  						HTTP: []api.PortRuleHTTP{
  1928  							{Method: "GET", Path: "/"},
  1929  						},
  1930  					},
  1931  				}},
  1932  			},
  1933  			{
  1934  				FromEndpoints: []api.EndpointSelector{endpointSelectorC},
  1935  				ToPorts: []api.PortRule{{
  1936  					Ports: []api.PortProtocol{
  1937  						{Port: "80", Protocol: api.ProtoTCP},
  1938  					},
  1939  				}},
  1940  			},
  1941  		},
  1942  	}})
  1943  
  1944  	buffer := new(bytes.Buffer)
  1945  	ctx := SearchContext{To: labelsA, Trace: TRACE_VERBOSE}
  1946  	ctx.Logging = logging.NewLogBackend(buffer, "", 0)
  1947  
  1948  	l4IngressPolicy, err := repo.ResolveL4IngressPolicy(&ctx)
  1949  	c.Assert(err, IsNil)
  1950  
  1951  	c.Log(buffer)
  1952  
  1953  	filter, ok := l4IngressPolicy["80/TCP"]
  1954  	c.Assert(ok, Equals, true)
  1955  	c.Assert(filter.Port, Equals, 80)
  1956  	c.Assert(filter.Ingress, Equals, true)
  1957  
  1958  	c.Assert(len(filter.CachedSelectors), Equals, 2)
  1959  	c.Assert(filter.CachedSelectors[0], checker.Equals, wildcardCachedSelector)
  1960  	c.Assert(filter.CachedSelectors[1], checker.Equals, cachedSelectorC)
  1961  
  1962  	c.Assert(filter.L7Parser, Equals, ParserTypeHTTP)
  1963  	c.Assert(len(filter.L7RulesPerEp), Equals, 2)
  1964  	l4IngressPolicy.Detach(repo.GetSelectorCache())
  1965  
  1966  	repo = parseAndAddRules(c, api.Rules{&api.Rule{
  1967  		EndpointSelector: endpointSelectorA,
  1968  		Ingress: []api.IngressRule{
  1969  			{
  1970  				FromEndpoints: []api.EndpointSelector{endpointSelectorC},
  1971  				ToPorts: []api.PortRule{{
  1972  					Ports: []api.PortProtocol{
  1973  						{Port: "80", Protocol: api.ProtoTCP},
  1974  					},
  1975  				}},
  1976  			},
  1977  			{
  1978  				ToPorts: []api.PortRule{{
  1979  					Ports: []api.PortProtocol{
  1980  						{Port: "80", Protocol: api.ProtoTCP},
  1981  					},
  1982  					Rules: &api.L7Rules{
  1983  						HTTP: []api.PortRuleHTTP{
  1984  							{Method: "GET", Path: "/"},
  1985  						},
  1986  					},
  1987  				}},
  1988  			},
  1989  		},
  1990  	}})
  1991  
  1992  	buffer = new(bytes.Buffer)
  1993  	ctx = SearchContext{To: labelsA, Trace: TRACE_VERBOSE}
  1994  	ctx.Logging = logging.NewLogBackend(buffer, "", 0)
  1995  
  1996  	l4IngressPolicy, err = repo.ResolveL4IngressPolicy(&ctx)
  1997  	c.Assert(err, IsNil)
  1998  
  1999  	c.Log(buffer)
  2000  
  2001  	filter, ok = l4IngressPolicy["80/TCP"]
  2002  	c.Assert(ok, Equals, true)
  2003  	c.Assert(filter.Port, Equals, 80)
  2004  	c.Assert(filter.Ingress, Equals, true)
  2005  
  2006  	c.Assert(len(filter.CachedSelectors), Equals, 2)
  2007  	c.Assert(filter.CachedSelectors[0], checker.Equals, wildcardCachedSelector)
  2008  	c.Assert(filter.CachedSelectors[1], checker.Equals, cachedSelectorC)
  2009  
  2010  	c.Assert(filter.L7Parser, Equals, ParserTypeHTTP)
  2011  	c.Assert(len(filter.L7RulesPerEp), Equals, 2)
  2012  	l4IngressPolicy.Detach(repo.GetSelectorCache())
  2013  }
  2014  
  2015  func (ds *PolicyTestSuite) TestMatches(c *C) {
  2016  	repo := parseAndAddRules(c, api.Rules{&api.Rule{
  2017  		EndpointSelector: endpointSelectorA,
  2018  		Ingress: []api.IngressRule{
  2019  			{
  2020  				FromEndpoints: []api.EndpointSelector{endpointSelectorC},
  2021  			},
  2022  		},
  2023  	}})
  2024  
  2025  	addedRule := repo.rules[0]
  2026  
  2027  	selectedEpLabels := labels.ParseSelectLabel("id=a")
  2028  	selectedIdentity := identity2.NewIdentity(54321, labels.Labels{selectedEpLabels.Key: selectedEpLabels})
  2029  
  2030  	notSelectedEpLabels := labels.ParseSelectLabel("id=b")
  2031  	notSelectedIdentity := identity2.NewIdentity(9876, labels.Labels{notSelectedEpLabels.Key: notSelectedEpLabels})
  2032  
  2033  	// notSelectedEndpoint is not selected by rule, so we it shouldn't be added
  2034  	// to EndpointsSelected.
  2035  	c.Assert(addedRule.matches(notSelectedIdentity), Equals, false)
  2036  	c.Assert(addedRule.metadata.IdentitySelected, checker.DeepEquals, map[identity.NumericIdentity]bool{notSelectedIdentity.ID: false})
  2037  
  2038  	// selectedEndpoint is selected by rule, so we it should be added to
  2039  	// EndpointsSelected.
  2040  	c.Assert(addedRule.matches(selectedIdentity), Equals, true)
  2041  	c.Assert(addedRule.metadata.IdentitySelected, checker.DeepEquals, map[identity.NumericIdentity]bool{selectedIdentity.ID: true, notSelectedIdentity.ID: false})
  2042  
  2043  	// Test again to check for caching working correctly.
  2044  	c.Assert(addedRule.matches(selectedIdentity), Equals, true)
  2045  	c.Assert(addedRule.metadata.IdentitySelected, checker.DeepEquals, map[identity.NumericIdentity]bool{selectedIdentity.ID: true, notSelectedIdentity.ID: false})
  2046  
  2047  	// Possible scenario where an endpoint is deleted, and soon after another
  2048  	// endpoint is added with the same ID, but with a different identity. Matching
  2049  	// needs to handle this case correctly.
  2050  	c.Assert(addedRule.matches(notSelectedIdentity), Equals, false)
  2051  	c.Assert(addedRule.metadata.IdentitySelected, checker.DeepEquals, map[identity.NumericIdentity]bool{selectedIdentity.ID: true, notSelectedIdentity.ID: false})
  2052  }