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