github.phpd.cn/cilium/cilium@v1.6.12/daemon/policy_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 main
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"os"
    23  	"sort"
    24  	"time"
    25  
    26  	"github.com/cilium/cilium/common/addressing"
    27  	"github.com/cilium/cilium/pkg/checker"
    28  	"github.com/cilium/cilium/pkg/endpoint"
    29  	"github.com/cilium/cilium/pkg/endpoint/regeneration"
    30  	"github.com/cilium/cilium/pkg/identity"
    31  	"github.com/cilium/cilium/pkg/identity/cache"
    32  	"github.com/cilium/cilium/pkg/labels"
    33  	"github.com/cilium/cilium/pkg/mac"
    34  	"github.com/cilium/cilium/pkg/policy/api"
    35  	"github.com/cilium/cilium/pkg/testutils"
    36  
    37  	cilium "github.com/cilium/proxy/go/cilium/api"
    38  	envoy_api_v2_core "github.com/cilium/proxy/go/envoy/api/v2/core"
    39  	envoy_api_v2_route "github.com/cilium/proxy/go/envoy/api/v2/route"
    40  	envoy_type_matcher "github.com/cilium/proxy/go/envoy/type/matcher"
    41  
    42  	"github.com/golang/protobuf/ptypes/wrappers"
    43  
    44  	. "gopkg.in/check.v1"
    45  )
    46  
    47  var (
    48  	QAHardAddr      = mac.MAC{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}
    49  	QAIPv6Addr, _   = addressing.NewCiliumIPv6("beef:beef:beef:beef:aaaa:aaaa:1111:1112")
    50  	QAIPv4Addr, _   = addressing.NewCiliumIPv4("10.11.12.13")
    51  	ProdHardAddr    = mac.MAC{0x01, 0x07, 0x08, 0x09, 0x0a, 0x0b}
    52  	ProdIPv6Addr, _ = addressing.NewCiliumIPv6("cafe:cafe:cafe:cafe:aaaa:aaaa:1111:1112")
    53  	ProdIPv4Addr, _ = addressing.NewCiliumIPv4("10.11.12.14")
    54  
    55  	lblProd = labels.ParseLabel("Prod")
    56  	lblQA   = labels.ParseLabel("QA")
    57  	lblFoo  = labels.ParseLabel("foo")
    58  	lblBar  = labels.ParseLabel("bar")
    59  	lblJoe  = labels.ParseLabel("user=joe")
    60  	lblPete = labels.ParseLabel("user=pete")
    61  
    62  	testEndpointID = uint16(1)
    63  
    64  	regenerationMetadata = &regeneration.ExternalRegenerationMetadata{
    65  		Reason: "test",
    66  	}
    67  
    68  	CNPAllowTCP80 = api.PortRule{
    69  		Ports: []api.PortProtocol{
    70  			{Port: "80", Protocol: api.ProtoTCP},
    71  		},
    72  	}
    73  	CNPAllowGETbar = api.PortRule{
    74  		Ports: CNPAllowTCP80.Ports,
    75  		Rules: &api.L7Rules{
    76  			HTTP: []api.PortRuleHTTP{
    77  				{
    78  					Path:   "/bar",
    79  					Method: "GET",
    80  				},
    81  			},
    82  		},
    83  	}
    84  
    85  	PNPAllowAll = cilium.PortNetworkPolicyRule_HttpRules{
    86  		HttpRules: &cilium.HttpNetworkPolicyRules{
    87  			HttpRules: []*cilium.HttpNetworkPolicyRule{
    88  				{},
    89  			},
    90  		},
    91  	}
    92  	googleRe2 = &envoy_type_matcher.RegexMatcher_GoogleRe2{
    93  		GoogleRe2: &envoy_type_matcher.RegexMatcher_GoogleRE2{
    94  			MaxProgramSize: &wrappers.UInt32Value{Value: 100}, // Envoy default
    95  		}}
    96  
    97  	PNPAllowGETbar = cilium.PortNetworkPolicyRule_HttpRules{
    98  		HttpRules: &cilium.HttpNetworkPolicyRules{
    99  			HttpRules: []*cilium.HttpNetworkPolicyRule{
   100  				{
   101  					Headers: []*envoy_api_v2_route.HeaderMatcher{
   102  						{
   103  							Name: ":method",
   104  							HeaderMatchSpecifier: &envoy_api_v2_route.HeaderMatcher_SafeRegexMatch{
   105  								SafeRegexMatch: &envoy_type_matcher.RegexMatcher{
   106  									EngineType: googleRe2,
   107  									Regex:      "GET",
   108  								}},
   109  						},
   110  						{
   111  							Name: ":path",
   112  							HeaderMatchSpecifier: &envoy_api_v2_route.HeaderMatcher_SafeRegexMatch{
   113  								SafeRegexMatch: &envoy_type_matcher.RegexMatcher{
   114  									EngineType: googleRe2,
   115  									Regex:      "/bar",
   116  								}},
   117  						},
   118  					},
   119  				},
   120  			},
   121  		},
   122  	}
   123  )
   124  
   125  // getXDSNetworkPolicies returns the representation of the xDS network policies
   126  // as a map of IP addresses to NetworkPolicy objects
   127  func (ds *DaemonSuite) getXDSNetworkPolicies(c *C, resourceNames []string) map[string]*cilium.NetworkPolicy {
   128  	networkPolicies, err := ds.d.l7Proxy.GetNetworkPolicies(resourceNames)
   129  	c.Assert(err, IsNil)
   130  	return networkPolicies
   131  }
   132  
   133  func prepareEndpointDirs() (cleanup func(), err error) {
   134  	testEPDir := fmt.Sprintf("%d", testEndpointID)
   135  	if err = os.Mkdir(testEPDir, 755); err != nil {
   136  		return func() {}, err
   137  	}
   138  	return func() {
   139  		os.RemoveAll(fmt.Sprintf("%s/lxc_config.h", testEPDir))
   140  		time.Sleep(1 * time.Second)
   141  		os.RemoveAll(testEPDir)
   142  		os.RemoveAll(fmt.Sprintf("%s_backup", testEPDir))
   143  	}, nil
   144  }
   145  
   146  func (ds *DaemonSuite) prepareEndpoint(c *C, identity *identity.Identity, qa bool) *endpoint.Endpoint {
   147  	e := endpoint.NewEndpointWithState(ds.d, testEndpointID, endpoint.StateWaitingForIdentity)
   148  	e.IfName = "dummy1"
   149  	if qa {
   150  		e.IPv6 = QAIPv6Addr
   151  		e.IPv4 = QAIPv4Addr
   152  		e.LXCMAC = QAHardAddr
   153  		e.SetNodeMACLocked(QAHardAddr)
   154  	} else {
   155  		e.IPv6 = ProdIPv6Addr
   156  		e.IPv4 = ProdIPv4Addr
   157  		e.LXCMAC = ProdHardAddr
   158  		e.SetNodeMACLocked(ProdHardAddr)
   159  	}
   160  	e.SetIdentity(identity, true)
   161  
   162  	e.UnconditionalLock()
   163  	ready := e.SetStateLocked(endpoint.StateWaitingToRegenerate, "test")
   164  	e.Unlock()
   165  	c.Assert(ready, Equals, true)
   166  	buildSuccess := <-e.Regenerate(regenerationMetadata)
   167  	c.Assert(buildSuccess, Equals, true)
   168  
   169  	return e
   170  }
   171  
   172  func (ds *DaemonSuite) regenerateEndpoint(c *C, e *endpoint.Endpoint) {
   173  	e.UnconditionalLock()
   174  	ready := e.SetStateLocked(endpoint.StateWaitingToRegenerate, "test")
   175  	e.Unlock()
   176  	c.Assert(ready, Equals, true)
   177  	buildSuccess := <-e.Regenerate(regenerationMetadata)
   178  	c.Assert(buildSuccess, Equals, true)
   179  }
   180  
   181  func (ds *DaemonSuite) TestUpdateConsumerMap(c *C) {
   182  	rules := api.Rules{
   183  		{
   184  			EndpointSelector: api.NewESFromLabels(lblBar),
   185  			Ingress: []api.IngressRule{
   186  				{
   187  					FromEndpoints: []api.EndpointSelector{
   188  						api.NewESFromLabels(lblJoe),
   189  						api.NewESFromLabels(lblPete),
   190  						api.NewESFromLabels(lblFoo),
   191  					},
   192  				},
   193  				{
   194  					FromEndpoints: []api.EndpointSelector{
   195  						api.NewESFromLabels(lblFoo),
   196  					},
   197  					ToPorts: []api.PortRule{
   198  						// Allow Port 80 GET /bar
   199  						CNPAllowGETbar,
   200  					},
   201  				},
   202  			},
   203  		},
   204  		{
   205  			EndpointSelector: api.NewESFromLabels(lblQA),
   206  			Ingress: []api.IngressRule{
   207  				{
   208  					FromRequires: []api.EndpointSelector{
   209  						api.NewESFromLabels(lblQA),
   210  					},
   211  				},
   212  			},
   213  		},
   214  		{
   215  			EndpointSelector: api.NewESFromLabels(lblProd),
   216  			Ingress: []api.IngressRule{
   217  				{
   218  					FromRequires: []api.EndpointSelector{
   219  						api.NewESFromLabels(lblProd),
   220  					},
   221  				},
   222  			},
   223  		},
   224  	}
   225  
   226  	ds.d.l7Proxy.RemoveAllNetworkPolicies()
   227  
   228  	_, err3 := ds.d.PolicyAdd(rules, nil)
   229  	c.Assert(err3, Equals, nil)
   230  
   231  	// Prepare the identities necessary for testing
   232  	qaBarLbls := labels.Labels{lblBar.Key: lblBar, lblQA.Key: lblQA}
   233  	qaBarSecLblsCtx, _, err := cache.AllocateIdentity(context.Background(), ds.d, qaBarLbls)
   234  	c.Assert(err, Equals, nil)
   235  	defer cache.Release(context.Background(), ds.d, qaBarSecLblsCtx)
   236  	prodBarLbls := labels.Labels{lblBar.Key: lblBar, lblProd.Key: lblProd}
   237  	prodBarSecLblsCtx, _, err := cache.AllocateIdentity(context.Background(), ds.d, prodBarLbls)
   238  	c.Assert(err, Equals, nil)
   239  	defer cache.Release(context.Background(), ds.d, prodBarSecLblsCtx)
   240  	qaFooLbls := labels.Labels{lblFoo.Key: lblFoo, lblQA.Key: lblQA}
   241  	qaFooSecLblsCtx, _, err := cache.AllocateIdentity(context.Background(), ds.d, qaFooLbls)
   242  	c.Assert(err, Equals, nil)
   243  	defer cache.Release(context.Background(), ds.d, qaFooSecLblsCtx)
   244  	prodFooLbls := labels.Labels{lblFoo.Key: lblFoo, lblProd.Key: lblProd}
   245  	prodFooSecLblsCtx, _, err := cache.AllocateIdentity(context.Background(), ds.d, prodFooLbls)
   246  	c.Assert(err, Equals, nil)
   247  	defer cache.Release(context.Background(), ds.d, prodFooSecLblsCtx)
   248  	prodFooJoeLbls := labels.Labels{lblFoo.Key: lblFoo, lblProd.Key: lblProd, lblJoe.Key: lblJoe}
   249  	prodFooJoeSecLblsCtx, _, err := cache.AllocateIdentity(context.Background(), ds.d, prodFooJoeLbls)
   250  	c.Assert(err, Equals, nil)
   251  	defer cache.Release(context.Background(), ds.d, prodFooJoeSecLblsCtx)
   252  
   253  	// Prepare endpoints
   254  	cleanup, err2 := prepareEndpointDirs()
   255  	c.Assert(err2, Equals, nil)
   256  	defer cleanup()
   257  
   258  	e := ds.prepareEndpoint(c, qaBarSecLblsCtx, true)
   259  	c.Assert(e.Allows(qaBarSecLblsCtx.ID), Equals, false)
   260  	c.Assert(e.Allows(prodBarSecLblsCtx.ID), Equals, false)
   261  	c.Assert(e.Allows(qaFooSecLblsCtx.ID), Equals, true)
   262  	c.Assert(e.Allows(prodFooSecLblsCtx.ID), Equals, false)
   263  
   264  	e = ds.prepareEndpoint(c, prodBarSecLblsCtx, false)
   265  	c.Assert(e.Allows(0), Equals, false)
   266  	c.Assert(e.Allows(qaBarSecLblsCtx.ID), Equals, false)
   267  	c.Assert(e.Allows(prodBarSecLblsCtx.ID), Equals, false)
   268  	c.Assert(e.Allows(qaFooSecLblsCtx.ID), Equals, false)
   269  	c.Assert(e.Allows(prodFooSecLblsCtx.ID), Equals, true)
   270  	c.Assert(e.Allows(prodFooJoeSecLblsCtx.ID), Equals, true)
   271  
   272  	// Check that both policies have been updated in the xDS cache for the L7
   273  	// proxies.
   274  	networkPolicies := ds.getXDSNetworkPolicies(c, nil)
   275  	c.Assert(networkPolicies, HasLen, 4)
   276  
   277  	qaBarNetworkPolicy := networkPolicies[QAIPv4Addr.String()]
   278  	c.Assert(qaBarNetworkPolicy, Not(IsNil))
   279  	expectedRemotePolicies := []uint64{
   280  		uint64(qaFooSecLblsCtx.ID),
   281  		// The prodFoo* identities are allowed by FromEndpoints but rejected by
   282  		// FromRequires, so they are not included in the remote policies:
   283  		// uint64(prodFooSecLblsCtx.ID),
   284  		// uint64(prodFooJoeSecLblsCtx.ID),
   285  	}
   286  	sort.Slice(expectedRemotePolicies, func(i, j int) bool {
   287  		return expectedRemotePolicies[i] < expectedRemotePolicies[j]
   288  	})
   289  	expectedNetworkPolicy := &cilium.NetworkPolicy{
   290  		Name:             QAIPv4Addr.String(),
   291  		Policy:           uint64(qaBarSecLblsCtx.ID),
   292  		ConntrackMapName: "global",
   293  		IngressPerPortPolicies: []*cilium.PortNetworkPolicy{
   294  			{
   295  				Port:     80,
   296  				Protocol: envoy_api_v2_core.SocketAddress_TCP,
   297  				Rules: []*cilium.PortNetworkPolicyRule{
   298  					{
   299  						RemotePolicies: expectedRemotePolicies,
   300  						L7:             &PNPAllowAll,
   301  					},
   302  					//{
   303  					//	RemotePolicies: expectedRemotePolicies,
   304  					//	L7:             &PNPAllowGETbar,
   305  					//},
   306  				},
   307  			},
   308  		},
   309  		EgressPerPortPolicies: []*cilium.PortNetworkPolicy{ // Allow-all policy.
   310  			{Protocol: envoy_api_v2_core.SocketAddress_TCP},
   311  			{Protocol: envoy_api_v2_core.SocketAddress_UDP},
   312  		},
   313  	}
   314  	c.Assert(qaBarNetworkPolicy, checker.Equals, expectedNetworkPolicy)
   315  
   316  	prodBarNetworkPolicy := networkPolicies[ProdIPv4Addr.String()]
   317  	c.Assert(prodBarNetworkPolicy, Not(IsNil))
   318  	expectedRemotePolicies = []uint64{
   319  		// The qaFoo identity is allowed by FromEndpoints but rejected by
   320  		// FromRequires, so it is not included in the remote policies:
   321  		// uint64(qaFooSecLblsCtx.ID),
   322  		uint64(prodFooSecLblsCtx.ID),
   323  		uint64(prodFooJoeSecLblsCtx.ID),
   324  	}
   325  	sort.Slice(expectedRemotePolicies, func(i, j int) bool {
   326  		return expectedRemotePolicies[i] < expectedRemotePolicies[j]
   327  	})
   328  	expectedRemotePolicies2 := []uint64{
   329  		uint64(prodFooJoeSecLblsCtx.ID),
   330  	}
   331  	sort.Slice(expectedRemotePolicies2, func(i, j int) bool {
   332  		return expectedRemotePolicies2[i] < expectedRemotePolicies2[j]
   333  	})
   334  
   335  	expectedNetworkPolicy = &cilium.NetworkPolicy{
   336  		Name:             ProdIPv4Addr.String(),
   337  		Policy:           uint64(prodBarSecLblsCtx.ID),
   338  		ConntrackMapName: "global",
   339  		IngressPerPortPolicies: []*cilium.PortNetworkPolicy{
   340  			{
   341  				Port:     80,
   342  				Protocol: envoy_api_v2_core.SocketAddress_TCP,
   343  				Rules: []*cilium.PortNetworkPolicyRule{
   344  					{
   345  						RemotePolicies: expectedRemotePolicies2,
   346  						L7:             &PNPAllowAll,
   347  					},
   348  					{
   349  						RemotePolicies: expectedRemotePolicies,
   350  						L7:             &PNPAllowAll,
   351  					},
   352  					//{
   353  					//	RemotePolicies: expectedRemotePolicies,
   354  					//	L7:             &PNPAllowGETbar,
   355  					//},
   356  				},
   357  			},
   358  		},
   359  		EgressPerPortPolicies: []*cilium.PortNetworkPolicy{ // Allow-all policy.
   360  			{Protocol: envoy_api_v2_core.SocketAddress_TCP},
   361  			{Protocol: envoy_api_v2_core.SocketAddress_UDP},
   362  		},
   363  	}
   364  	c.Assert(prodBarNetworkPolicy, checker.Equals, expectedNetworkPolicy)
   365  }
   366  
   367  func (ds *DaemonSuite) TestL4_L7_Shadowing(c *C) {
   368  	// Prepare the identities necessary for testing
   369  	qaBarLbls := labels.Labels{lblBar.Key: lblBar, lblQA.Key: lblQA}
   370  	qaBarSecLblsCtx, _, err := cache.AllocateIdentity(context.Background(), ds.d, qaBarLbls)
   371  	c.Assert(err, Equals, nil)
   372  	defer cache.Release(context.Background(), ds.d, qaBarSecLblsCtx)
   373  	qaFooLbls := labels.Labels{lblFoo.Key: lblFoo, lblQA.Key: lblQA}
   374  	qaFooSecLblsCtx, _, err := cache.AllocateIdentity(context.Background(), ds.d, qaFooLbls)
   375  	c.Assert(err, Equals, nil)
   376  	defer cache.Release(context.Background(), ds.d, qaFooSecLblsCtx)
   377  
   378  	rules := api.Rules{
   379  		{
   380  			EndpointSelector: api.NewESFromLabels(lblBar),
   381  			Ingress: []api.IngressRule{
   382  				{
   383  					ToPorts: []api.PortRule{
   384  						// Allow all on port 80 (no proxy)
   385  						CNPAllowTCP80,
   386  					},
   387  				},
   388  				{
   389  					FromEndpoints: []api.EndpointSelector{
   390  						api.NewESFromLabels(lblFoo),
   391  					},
   392  					ToPorts: []api.PortRule{
   393  						// Allow Port 80 GET /bar
   394  						CNPAllowGETbar,
   395  					},
   396  				},
   397  			},
   398  		},
   399  	}
   400  
   401  	ds.d.l7Proxy.RemoveAllNetworkPolicies()
   402  
   403  	_, err = ds.d.PolicyAdd(rules, nil)
   404  	c.Assert(err, Equals, nil)
   405  
   406  	// Prepare endpoints
   407  	cleanup, err := prepareEndpointDirs()
   408  	c.Assert(err, Equals, nil)
   409  	defer cleanup()
   410  
   411  	e := ds.prepareEndpoint(c, qaBarSecLblsCtx, true)
   412  	c.Assert(e.Allows(qaBarSecLblsCtx.ID), Equals, false)
   413  	c.Assert(e.Allows(qaFooSecLblsCtx.ID), Equals, false)
   414  
   415  	// Check that both policies have been updated in the xDS cache for the L7
   416  	// proxies.
   417  	networkPolicies := ds.getXDSNetworkPolicies(c, nil)
   418  	c.Assert(networkPolicies, HasLen, 2)
   419  
   420  	qaBarNetworkPolicy := networkPolicies[QAIPv4Addr.String()]
   421  	expectedNetworkPolicy := &cilium.NetworkPolicy{
   422  		Name:             QAIPv4Addr.String(),
   423  		Policy:           uint64(qaBarSecLblsCtx.ID),
   424  		ConntrackMapName: "global",
   425  		IngressPerPortPolicies: []*cilium.PortNetworkPolicy{
   426  			{
   427  				Port:     80,
   428  				Protocol: envoy_api_v2_core.SocketAddress_TCP,
   429  				Rules: []*cilium.PortNetworkPolicyRule{
   430  					{
   431  						RemotePolicies: nil,
   432  						L7:             &PNPAllowAll,
   433  					},
   434  					{
   435  						RemotePolicies: []uint64{uint64(qaFooSecLblsCtx.ID)},
   436  						L7:             &PNPAllowGETbar,
   437  					},
   438  				},
   439  			},
   440  		},
   441  		EgressPerPortPolicies: []*cilium.PortNetworkPolicy{ // Allow-all policy.
   442  			{Protocol: envoy_api_v2_core.SocketAddress_TCP},
   443  			{Protocol: envoy_api_v2_core.SocketAddress_UDP},
   444  		},
   445  	}
   446  	c.Assert(qaBarNetworkPolicy, checker.Equals, expectedNetworkPolicy)
   447  }
   448  
   449  func (ds *DaemonSuite) TestReplacePolicy(c *C) {
   450  	lbls := labels.ParseLabelArray("foo", "bar")
   451  	rules := api.Rules{
   452  		{
   453  			Labels:           lbls,
   454  			EndpointSelector: api.NewESFromLabels(lblBar),
   455  			Egress:           []api.EgressRule{{ToCIDR: []api.CIDR{"1.1.1.1/32", "2.2.2.0/24"}}},
   456  		},
   457  		{
   458  			Labels:           lbls,
   459  			EndpointSelector: api.NewESFromLabels(lblBar),
   460  		},
   461  	}
   462  
   463  	_, err := ds.d.PolicyAdd(rules, nil)
   464  	c.Assert(err, IsNil)
   465  	ds.d.policy.Mutex.RLock()
   466  	c.Assert(len(ds.d.policy.SearchRLocked(lbls)), Equals, 2)
   467  	ds.d.policy.Mutex.RUnlock()
   468  	rules[0].Egress = []api.EgressRule{{ToCIDR: []api.CIDR{"1.1.1.1/32", "2.2.2.2/32"}}}
   469  	_, err = ds.d.PolicyAdd(rules, &AddOptions{Replace: true})
   470  
   471  	c.Assert(err, IsNil)
   472  	ds.d.policy.Mutex.RLock()
   473  	c.Assert(len(ds.d.policy.SearchRLocked(lbls)), Equals, 2)
   474  	ds.d.policy.Mutex.RUnlock()
   475  
   476  	// Updating of prefix lengths may complete *after* PolicyAdd returns. Add a
   477  	// wait for prefix lengths to be correct after timeout to ensure that we
   478  	// do not assert before the releasing of CIDRs has been performed.
   479  	testutils.WaitUntil(func() bool {
   480  		_, s4 := ds.d.prefixLengths.ToBPFData()
   481  		sort.Ints(s4)
   482  		if len(s4) != 2 {
   483  			c.Logf("IPv4 Prefix lengths incorrect (expected [0, 32]). This may be because CIDRs were not released on replace. %+v", s4)
   484  			return false
   485  		}
   486  		for i, v := range []int{0, 32} {
   487  			if s4[i] != v {
   488  				c.Logf("Unexpected IPv4 Prefix length. This may be because CIDRs were not released on replace. %+v", s4)
   489  				return false
   490  			}
   491  		}
   492  		return true
   493  	}, time.Second*5)
   494  }
   495  
   496  func (ds *DaemonSuite) TestRemovePolicy(c *C) {
   497  	qaBarLbls := labels.Labels{lblBar.Key: lblBar, lblQA.Key: lblQA}
   498  	qaBarSecLblsCtx, _, err := cache.AllocateIdentity(context.Background(), ds.d, qaBarLbls)
   499  	c.Assert(err, Equals, nil)
   500  	defer cache.Release(context.Background(), ds.d, qaBarSecLblsCtx)
   501  
   502  	rules := api.Rules{
   503  		{
   504  			EndpointSelector: api.NewESFromLabels(lblBar),
   505  			Ingress: []api.IngressRule{
   506  				{
   507  					FromEndpoints: []api.EndpointSelector{
   508  						api.NewESFromLabels(lblJoe),
   509  						api.NewESFromLabels(lblPete),
   510  						api.NewESFromLabels(lblFoo),
   511  					},
   512  				},
   513  				{
   514  					FromEndpoints: []api.EndpointSelector{
   515  						api.NewESFromLabels(lblFoo),
   516  					},
   517  					ToPorts: []api.PortRule{
   518  						// Allow Port 80 GET /bar
   519  						CNPAllowGETbar,
   520  					},
   521  				},
   522  			},
   523  		},
   524  		{
   525  			EndpointSelector: api.NewESFromLabels(lblQA),
   526  			Ingress: []api.IngressRule{
   527  				{
   528  					FromRequires: []api.EndpointSelector{
   529  						api.NewESFromLabels(lblQA),
   530  					},
   531  				},
   532  			},
   533  		},
   534  		{
   535  			EndpointSelector: api.NewESFromLabels(lblProd),
   536  			Ingress: []api.IngressRule{
   537  				{
   538  					FromRequires: []api.EndpointSelector{
   539  						api.NewESFromLabels(lblProd),
   540  					},
   541  				},
   542  			},
   543  		},
   544  	}
   545  
   546  	ds.d.l7Proxy.RemoveAllNetworkPolicies()
   547  
   548  	_, err3 := ds.d.PolicyAdd(rules, nil)
   549  	c.Assert(err3, Equals, nil)
   550  
   551  	cleanup, err2 := prepareEndpointDirs()
   552  	c.Assert(err2, Equals, nil)
   553  	defer cleanup()
   554  
   555  	// Create the endpoint and generate its policy.
   556  	e := ds.prepareEndpoint(c, qaBarSecLblsCtx, true)
   557  
   558  	// Check that the policy has been updated in the xDS cache for the L7
   559  	// proxies.
   560  	networkPolicies := ds.getXDSNetworkPolicies(c, nil)
   561  	c.Assert(networkPolicies, HasLen, 2)
   562  	qaBarNetworkPolicy := networkPolicies[QAIPv4Addr.String()]
   563  	c.Assert(qaBarNetworkPolicy, Not(IsNil))
   564  
   565  	// Delete the endpoint.
   566  	e.UnconditionalLock()
   567  	e.LeaveLocked(nil, endpoint.DeleteConfig{})
   568  	e.Unlock()
   569  
   570  	// Check that the policy has been removed from the xDS cache.
   571  	networkPolicies = ds.getXDSNetworkPolicies(c, nil)
   572  	c.Assert(networkPolicies, HasLen, 0)
   573  }
   574  
   575  func (ds *DaemonSuite) TestIncrementalPolicy(c *C) {
   576  	qaBarLbls := labels.Labels{lblBar.Key: lblBar, lblQA.Key: lblQA}
   577  	qaBarSecLblsCtx, _, err := cache.AllocateIdentity(context.Background(), ds.d, qaBarLbls)
   578  	c.Assert(err, Equals, nil)
   579  	defer cache.Release(context.Background(), ds.d, qaBarSecLblsCtx)
   580  
   581  	rules := api.Rules{
   582  		{
   583  			EndpointSelector: api.NewESFromLabels(lblBar),
   584  			Ingress: []api.IngressRule{
   585  				{
   586  					FromEndpoints: []api.EndpointSelector{
   587  						api.NewESFromLabels(lblJoe),
   588  						api.NewESFromLabels(lblPete),
   589  						api.NewESFromLabels(lblFoo),
   590  					},
   591  				},
   592  				{
   593  					FromEndpoints: []api.EndpointSelector{
   594  						api.NewESFromLabels(lblFoo),
   595  					},
   596  					ToPorts: []api.PortRule{
   597  						// Allow Port 80 GET /bar
   598  						CNPAllowGETbar,
   599  					},
   600  				},
   601  			},
   602  		},
   603  		{
   604  			EndpointSelector: api.NewESFromLabels(lblQA),
   605  			Ingress: []api.IngressRule{
   606  				{
   607  					FromRequires: []api.EndpointSelector{
   608  						api.NewESFromLabels(lblQA),
   609  					},
   610  				},
   611  			},
   612  		},
   613  		{
   614  			EndpointSelector: api.NewESFromLabels(lblProd),
   615  			Ingress: []api.IngressRule{
   616  				{
   617  					FromRequires: []api.EndpointSelector{
   618  						api.NewESFromLabels(lblProd),
   619  					},
   620  				},
   621  			},
   622  		},
   623  	}
   624  
   625  	ds.d.l7Proxy.RemoveAllNetworkPolicies()
   626  
   627  	_, err3 := ds.d.PolicyAdd(rules, nil)
   628  	c.Assert(err3, Equals, nil)
   629  
   630  	cleanup, err2 := prepareEndpointDirs()
   631  	c.Assert(err2, Equals, nil)
   632  	defer cleanup()
   633  
   634  	// Create the endpoint and generate its policy.
   635  	e := ds.prepareEndpoint(c, qaBarSecLblsCtx, true)
   636  
   637  	// Check that the policy has been updated in the xDS cache for the L7
   638  	// proxies.
   639  	networkPolicies := ds.getXDSNetworkPolicies(c, nil)
   640  	c.Assert(networkPolicies, HasLen, 2)
   641  	qaBarNetworkPolicy := networkPolicies[QAIPv4Addr.String()]
   642  	c.Assert(qaBarNetworkPolicy, Not(IsNil))
   643  
   644  	c.Assert(qaBarNetworkPolicy.IngressPerPortPolicies, HasLen, 0)
   645  
   646  	// Allocate identities needed for this test
   647  	qaFooLbls := labels.Labels{lblFoo.Key: lblFoo, lblQA.Key: lblQA}
   648  	qaFooID, _, err := cache.AllocateIdentity(context.Background(), ds.d, qaFooLbls)
   649  	c.Assert(err, Equals, nil)
   650  	defer cache.Release(context.Background(), ds.d, qaFooID)
   651  
   652  	// Regenerate endpoint
   653  	ds.regenerateEndpoint(c, e)
   654  
   655  	// Check that the policy has been updated in the xDS cache for the L7
   656  	// proxies.
   657  	networkPolicies = ds.getXDSNetworkPolicies(c, nil)
   658  	c.Assert(networkPolicies, HasLen, 2)
   659  	qaBarNetworkPolicy = networkPolicies[QAIPv4Addr.String()]
   660  	c.Assert(qaBarNetworkPolicy, Not(IsNil))
   661  
   662  	c.Assert(qaBarNetworkPolicy.IngressPerPortPolicies, HasLen, 1)
   663  	c.Assert(qaBarNetworkPolicy.IngressPerPortPolicies[0].Rules, HasLen, 1)
   664  	c.Assert(qaBarNetworkPolicy.IngressPerPortPolicies[0].Rules[0].RemotePolicies, HasLen, 1)
   665  	c.Assert(qaBarNetworkPolicy.IngressPerPortPolicies[0].Rules[0].RemotePolicies[0], Equals, uint64(qaFooID.ID))
   666  
   667  	// Delete the endpoint.
   668  	e.UnconditionalLock()
   669  	e.LeaveLocked(nil, endpoint.DeleteConfig{})
   670  	e.Unlock()
   671  
   672  	// Check that the policy has been removed from the xDS cache.
   673  	networkPolicies = ds.getXDSNetworkPolicies(c, nil)
   674  	c.Assert(networkPolicies, HasLen, 0)
   675  }