github.phpd.cn/cilium/cilium@v1.6.12/pkg/k8s/network_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 k8s
    18  
    19  import (
    20  	"encoding/json"
    21  	"fmt"
    22  	"testing"
    23  
    24  	"github.com/cilium/cilium/api/v1/models"
    25  	"github.com/cilium/cilium/pkg/annotation"
    26  	"github.com/cilium/cilium/pkg/checker"
    27  	"github.com/cilium/cilium/pkg/identity"
    28  	k8sConst "github.com/cilium/cilium/pkg/k8s/apis/cilium.io"
    29  	"github.com/cilium/cilium/pkg/labels"
    30  	"github.com/cilium/cilium/pkg/policy"
    31  	"github.com/cilium/cilium/pkg/policy/api"
    32  	"github.com/cilium/cilium/pkg/testutils"
    33  
    34  	. "gopkg.in/check.v1"
    35  	v1 "k8s.io/api/core/v1"
    36  	networkingv1 "k8s.io/api/networking/v1"
    37  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    38  	"k8s.io/apimachinery/pkg/types"
    39  	"k8s.io/apimachinery/pkg/util/intstr"
    40  )
    41  
    42  // Hook up gocheck into the "go test" runner.
    43  func Test(t *testing.T) {
    44  	TestingT(t)
    45  }
    46  
    47  type K8sSuite struct{}
    48  
    49  var _ = Suite(&K8sSuite{})
    50  
    51  var (
    52  	labelsA = labels.LabelArray{
    53  		labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
    54  		labels.NewLabel("id", "a", labels.LabelSourceK8s),
    55  	}
    56  
    57  	labelSelectorA = metav1.LabelSelector{
    58  		MatchLabels: map[string]string{
    59  			"id": "a",
    60  		},
    61  	}
    62  
    63  	labelsB = labels.LabelArray{
    64  		labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
    65  		labels.NewLabel("id1", "b", labels.LabelSourceK8s),
    66  		labels.NewLabel("id2", "c", labels.LabelSourceK8s),
    67  	}
    68  
    69  	labelsC = labels.LabelArray{
    70  		labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
    71  		labels.NewLabel("id", "c", labels.LabelSourceK8s),
    72  	}
    73  
    74  	labelSelectorC = metav1.LabelSelector{
    75  		MatchLabels: map[string]string{
    76  			"id": "c",
    77  		},
    78  	}
    79  
    80  	ctxAToB = policy.SearchContext{
    81  		From:  labelsA,
    82  		To:    labelsB,
    83  		Trace: policy.TRACE_VERBOSE,
    84  	}
    85  
    86  	ctxAToC = policy.SearchContext{
    87  		From:  labelsA,
    88  		To:    labelsC,
    89  		Trace: policy.TRACE_VERBOSE,
    90  	}
    91  
    92  	port80 = networkingv1.NetworkPolicyPort{
    93  		Port: &intstr.IntOrString{
    94  			Type:   intstr.Int,
    95  			IntVal: 80,
    96  		},
    97  	}
    98  
    99  	dummySelectorCacheUser = &DummySelectorCacheUser{}
   100  )
   101  
   102  type DummySelectorCacheUser struct{}
   103  
   104  func testNewPolicyRepository() *policy.Repository {
   105  	repo := policy.NewPolicyRepository()
   106  	repo.GetSelectorCache().SetLocalIdentityNotifier(testutils.NewDummyIdentityNotifier())
   107  	return repo
   108  }
   109  
   110  func (d *DummySelectorCacheUser) IdentitySelectionUpdated(selector policy.CachedSelector, selections, added, deleted []identity.NumericIdentity) {
   111  }
   112  
   113  func (s *K8sSuite) TestParseNetworkPolicyIngress(c *C) {
   114  	netPolicy := &networkingv1.NetworkPolicy{
   115  		Spec: networkingv1.NetworkPolicySpec{
   116  			PodSelector: metav1.LabelSelector{
   117  				MatchLabels: map[string]string{
   118  					"foo1": "bar1",
   119  					"foo2": "bar2",
   120  				},
   121  			},
   122  			Ingress: []networkingv1.NetworkPolicyIngressRule{
   123  				{
   124  					From: []networkingv1.NetworkPolicyPeer{
   125  						{
   126  							PodSelector: &metav1.LabelSelector{
   127  								MatchLabels: map[string]string{
   128  									"foo3": "bar3",
   129  									"foo4": "bar4",
   130  								},
   131  							},
   132  						},
   133  					},
   134  					Ports: []networkingv1.NetworkPolicyPort{
   135  						{
   136  							Port: &intstr.IntOrString{
   137  								Type:   intstr.Int,
   138  								IntVal: 80,
   139  							},
   140  						},
   141  					},
   142  				},
   143  			},
   144  		},
   145  	}
   146  
   147  	_, err := ParseNetworkPolicy(netPolicy)
   148  	c.Assert(err, IsNil)
   149  
   150  	fromEndpoints := labels.LabelArray{
   151  		labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
   152  		labels.NewLabel("foo3", "bar3", labels.LabelSourceK8s),
   153  		labels.NewLabel("foo4", "bar4", labels.LabelSourceK8s),
   154  	}
   155  
   156  	ctx := policy.SearchContext{
   157  		From: fromEndpoints,
   158  		To: labels.LabelArray{
   159  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
   160  			labels.NewLabel("foo1", "bar1", labels.LabelSourceK8s),
   161  			labels.NewLabel("foo2", "bar2", labels.LabelSourceK8s),
   162  		},
   163  		Trace: policy.TRACE_VERBOSE,
   164  	}
   165  
   166  	rules, err := ParseNetworkPolicy(netPolicy)
   167  	c.Assert(err, IsNil)
   168  	c.Assert(len(rules), Equals, 1)
   169  
   170  	repo := testNewPolicyRepository()
   171  
   172  	repo.AddList(rules)
   173  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Denied)
   174  
   175  	epSelector := api.NewESFromLabels(fromEndpoints...)
   176  	cachedEPSelector, _ := repo.GetSelectorCache().AddIdentitySelector(dummySelectorCacheUser, epSelector)
   177  	defer func() { repo.GetSelectorCache().RemoveSelector(cachedEPSelector, dummySelectorCacheUser) }()
   178  
   179  	ingressL4Policy, err := repo.ResolveL4IngressPolicy(&ctx)
   180  	c.Assert(ingressL4Policy, Not(IsNil))
   181  	c.Assert(err, IsNil)
   182  	c.Assert(ingressL4Policy, checker.Equals, policy.L4PolicyMap{
   183  		"80/TCP": {
   184  			Port: 80, Protocol: api.ProtoTCP, U8Proto: 6,
   185  			CachedSelectors: policy.CachedSelectorSlice{cachedEPSelector},
   186  			L7Parser:        policy.ParserTypeNone,
   187  			L7RulesPerEp:    policy.L7DataMap{},
   188  			Ingress:         true,
   189  			DerivedFromRules: []labels.LabelArray{
   190  				labels.ParseLabelArray(
   191  					"k8s:"+k8sConst.PolicyLabelName,
   192  					"k8s:"+k8sConst.PolicyLabelUID,
   193  					"k8s:"+k8sConst.PolicyLabelNamespace+"=default",
   194  					"k8s:"+k8sConst.PolicyLabelDerivedFrom+"="+resourceTypeNetworkPolicy,
   195  				),
   196  			},
   197  		},
   198  	})
   199  	ingressL4Policy.Detach(repo.GetSelectorCache())
   200  
   201  	ctx.To = labels.LabelArray{
   202  		labels.NewLabel("foo2", "bar2", labels.LabelSourceK8s),
   203  	}
   204  
   205  	// ctx.To needs to have all labels from the policy in order to be accepted
   206  	c.Assert(repo.AllowsIngressRLocked(&ctx), Not(Equals), api.Allowed)
   207  
   208  	ctx = policy.SearchContext{
   209  		From: labels.LabelArray{
   210  			labels.NewLabel("foo3", "bar3", labels.LabelSourceK8s),
   211  		},
   212  		To: labels.LabelArray{
   213  			labels.NewLabel("foo1", "bar1", labels.LabelSourceK8s),
   214  			labels.NewLabel("foo2", "bar2", labels.LabelSourceK8s),
   215  		},
   216  		Trace: policy.TRACE_VERBOSE,
   217  	}
   218  	// ctx.From also needs to have all labels from the policy in order to be accepted
   219  	c.Assert(repo.AllowsIngressRLocked(&ctx), Not(Equals), api.Allowed)
   220  }
   221  
   222  func (s *K8sSuite) TestParseNetworkPolicyMultipleSelectors(c *C) {
   223  
   224  	// Rule with multiple selectors in egress and ingress
   225  	ex1 := []byte(`{
   226  "kind":"NetworkPolicy",
   227  "apiVersion":"extensions/networkingv1",
   228  "metadata":{
   229    "name":"ingress-multiple-selectors"
   230  },
   231  "spec":{
   232    "podSelector":{
   233      "matchLabels":{
   234        "role":"backend"
   235      }
   236    },
   237    "egress":[
   238      {
   239        "ports":[
   240          {
   241            "protocol":"TCP",
   242            "port":5432
   243          }
   244        ],
   245        "to":[
   246          {
   247            "podSelector":{
   248              "matchLabels":{
   249                "app":"db1"
   250              }
   251            }
   252          },
   253          {
   254            "podSelector":{
   255              "matchLabels":{
   256                "app":"db2"
   257              }
   258            }
   259          }
   260        ]
   261      }
   262    ],
   263    "ingress":[
   264      {
   265        "from":[
   266          {
   267            "podSelector":{
   268              "matchLabels":{
   269                "role":"frontend"
   270              }
   271            },
   272            "namespaceSelector":{
   273              "matchLabels":{
   274                "project":"myproject"
   275              }
   276            }
   277          },
   278          {
   279            "podSelector":{
   280              "matchLabels":{
   281                "app":"inventory"
   282              }
   283            }
   284          }
   285        ]
   286      }
   287    ]
   288  }
   289  }`)
   290  
   291  	np := networkingv1.NetworkPolicy{}
   292  	err := json.Unmarshal(ex1, &np)
   293  	c.Assert(err, IsNil)
   294  
   295  	rules, err := ParseNetworkPolicy(&np)
   296  	c.Assert(err, IsNil)
   297  	c.Assert(len(rules), Equals, 1)
   298  
   299  	repo := testNewPolicyRepository()
   300  	repo.AddList(rules)
   301  
   302  	endpointLabels := labels.LabelArray{
   303  		labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
   304  		labels.NewLabel("role", "backend", labels.LabelSourceK8s),
   305  	}
   306  
   307  	// Ingress context
   308  	ctx := policy.SearchContext{
   309  		From: labels.LabelArray{
   310  			labels.NewLabel("role", "frontend", labels.LabelSourceK8s),
   311  		},
   312  		To:    endpointLabels,
   313  		Trace: policy.TRACE_VERBOSE,
   314  	}
   315  
   316  	// should be DENIED because ctx.From is missing the namespace selector
   317  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Denied)
   318  
   319  	ctx.From = labels.LabelArray{
   320  		labels.NewLabel("role", "frontend", labels.LabelSourceK8s),
   321  		labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "project"), "myproject", labels.LabelSourceK8s),
   322  	}
   323  
   324  	// should be ALLOWED with the namespace label properly set
   325  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Allowed)
   326  
   327  	ctx.From = labels.LabelArray{
   328  		labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
   329  		labels.NewLabel("app", "inventory", labels.LabelSourceK8s),
   330  	}
   331  
   332  	// should be ALLOWED since all rules in From must match
   333  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Allowed)
   334  
   335  	// Egress context
   336  	ctx = policy.SearchContext{
   337  		From: endpointLabels,
   338  		To: labels.LabelArray{
   339  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
   340  			labels.NewLabel("app", "db1", labels.LabelSourceK8s),
   341  		},
   342  		Trace: policy.TRACE_VERBOSE,
   343  	}
   344  
   345  	// should be DENIED because DPorts are missing in context
   346  	c.Assert(repo.AllowsEgressRLocked(&ctx), Equals, api.Denied)
   347  
   348  	ctx.DPorts = []*models.Port{{Port: 5432, Protocol: models.PortProtocolTCP}}
   349  
   350  	// should be ALLOWED with DPorts set correctly
   351  	c.Assert(repo.AllowsEgressRLocked(&ctx), Equals, api.Allowed)
   352  
   353  	ctx.To = labels.LabelArray{
   354  		labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
   355  		labels.NewLabel("app", "db2", labels.LabelSourceK8s),
   356  	}
   357  
   358  	// should be ALLOWED for db2 as well
   359  	c.Assert(repo.AllowsEgressRLocked(&ctx), Equals, api.Allowed)
   360  }
   361  
   362  func (s *K8sSuite) TestParseNetworkPolicyNoSelectors(c *C) {
   363  
   364  	// Ingress with neither pod nor namespace selector set.
   365  	ex1 := []byte(`{
   366  "kind": "NetworkPolicy",
   367  "apiVersion": "extensions/networkingv1",
   368  "metadata": {
   369    "name": "ingress-cidr-test",
   370    "namespace": "myns",
   371    "uid": "11bba160-ddca-11e8-b697-0800273b04ff"
   372  },
   373  "spec": {
   374    "podSelector": {
   375      "matchLabels": {
   376        "role": "backend"
   377      }
   378    },
   379    "ingress": [
   380      {
   381        "from": [
   382          {
   383            "ipBlock": {
   384              "cidr": "10.0.0.0/8",
   385  	          "except": [
   386  	            "10.96.0.0/12"
   387  	          ]
   388            }
   389          }
   390        ]
   391      }
   392    ]
   393  }
   394  }`)
   395  
   396  	fromEndpoints := labels.LabelArray{
   397  		labels.NewLabel(k8sConst.PodNamespaceLabel, "myns", labels.LabelSourceK8s),
   398  		labels.NewLabel("role", "backend", labels.LabelSourceK8s),
   399  	}
   400  
   401  	epSelector := api.NewESFromLabels(fromEndpoints...)
   402  	np := networkingv1.NetworkPolicy{}
   403  	err := json.Unmarshal(ex1, &np)
   404  	c.Assert(err, IsNil)
   405  
   406  	expectedRule := api.NewRule().
   407  		WithEndpointSelector(epSelector).
   408  		WithIngressRules([]api.IngressRule{
   409  			{
   410  				FromCIDRSet: []api.CIDRRule{
   411  					{
   412  						Cidr: api.CIDR("10.0.0.0/8"),
   413  						ExceptCIDRs: []api.CIDR{
   414  							"10.96.0.0/12",
   415  						},
   416  					},
   417  				},
   418  			},
   419  		}).
   420  		WithEgressRules([]api.EgressRule{}).
   421  		WithLabels(labels.ParseLabelArray(
   422  			"k8s:"+k8sConst.PolicyLabelName+"=ingress-cidr-test",
   423  			"k8s:"+k8sConst.PolicyLabelUID+"=11bba160-ddca-11e8-b697-0800273b04ff",
   424  			"k8s:"+k8sConst.PolicyLabelNamespace+"=myns",
   425  			"k8s:"+k8sConst.PolicyLabelDerivedFrom+"="+resourceTypeNetworkPolicy,
   426  		))
   427  
   428  	expectedRule.Sanitize()
   429  
   430  	expectedRules := api.Rules{
   431  		expectedRule,
   432  	}
   433  
   434  	rules, err := ParseNetworkPolicy(&np)
   435  	c.Assert(err, IsNil)
   436  	c.Assert(rules, NotNil)
   437  	c.Assert(rules, checker.DeepEquals, expectedRules)
   438  }
   439  
   440  func (s *K8sSuite) TestParseNetworkPolicyEgress(c *C) {
   441  
   442  	netPolicy := &networkingv1.NetworkPolicy{
   443  		Spec: networkingv1.NetworkPolicySpec{
   444  			PodSelector: metav1.LabelSelector{
   445  				MatchLabels: map[string]string{
   446  					"foo1": "bar1",
   447  					"foo2": "bar2",
   448  				},
   449  			},
   450  			Egress: []networkingv1.NetworkPolicyEgressRule{
   451  				{
   452  					To: []networkingv1.NetworkPolicyPeer{
   453  						{
   454  							PodSelector: &metav1.LabelSelector{
   455  								MatchLabels: map[string]string{
   456  									"foo3": "bar3",
   457  									"foo4": "bar4",
   458  								},
   459  							},
   460  						},
   461  					},
   462  					Ports: []networkingv1.NetworkPolicyPort{
   463  						{
   464  							Port: &intstr.IntOrString{
   465  								Type:   intstr.Int,
   466  								IntVal: 80,
   467  							},
   468  						},
   469  					},
   470  				},
   471  			},
   472  		},
   473  	}
   474  
   475  	rules, err := ParseNetworkPolicy(netPolicy)
   476  	c.Assert(err, IsNil)
   477  	c.Assert(len(rules), Equals, 1)
   478  
   479  	fromEndpoints := labels.LabelArray{
   480  		labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
   481  		labels.NewLabel("foo1", "bar1", labels.LabelSourceK8s),
   482  		labels.NewLabel("foo2", "bar2", labels.LabelSourceK8s),
   483  	}
   484  
   485  	toEndpoints := labels.LabelArray{
   486  		labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
   487  		labels.NewLabel("foo3", "bar3", labels.LabelSourceK8s),
   488  		labels.NewLabel("foo4", "bar4", labels.LabelSourceK8s),
   489  	}
   490  
   491  	ctx := policy.SearchContext{
   492  		From:  fromEndpoints,
   493  		To:    toEndpoints,
   494  		Trace: policy.TRACE_VERBOSE,
   495  	}
   496  
   497  	repo := testNewPolicyRepository()
   498  	repo.AddList(rules)
   499  	// Because search context did not contain port-specific policy, deny is
   500  	// expected.
   501  	c.Assert(repo.AllowsEgressRLocked(&ctx), Equals, api.Denied)
   502  
   503  	epSelector := api.NewESFromLabels(toEndpoints...)
   504  	cachedEPSelector, _ := repo.GetSelectorCache().AddIdentitySelector(dummySelectorCacheUser, epSelector)
   505  	defer func() { repo.GetSelectorCache().RemoveSelector(cachedEPSelector, dummySelectorCacheUser) }()
   506  
   507  	egressL4Policy, err := repo.ResolveL4EgressPolicy(&ctx)
   508  	c.Assert(egressL4Policy, Not(IsNil))
   509  	c.Assert(err, IsNil)
   510  	c.Assert(egressL4Policy, checker.DeepEquals, policy.L4PolicyMap{
   511  		"80/TCP": {
   512  			Port: 80, Protocol: api.ProtoTCP, U8Proto: 6,
   513  			CachedSelectors: policy.CachedSelectorSlice{cachedEPSelector},
   514  			L7Parser:        policy.ParserTypeNone,
   515  			L7RulesPerEp:    policy.L7DataMap{},
   516  			Ingress:         false,
   517  			DerivedFromRules: []labels.LabelArray{
   518  				labels.ParseLabelArray(
   519  					"k8s:"+k8sConst.PolicyLabelName,
   520  					"k8s:"+k8sConst.PolicyLabelUID,
   521  					"k8s:"+k8sConst.PolicyLabelNamespace+"=default",
   522  					"k8s:"+k8sConst.PolicyLabelDerivedFrom+"="+resourceTypeNetworkPolicy,
   523  				),
   524  			},
   525  		},
   526  	})
   527  	egressL4Policy.Detach(repo.GetSelectorCache())
   528  
   529  	ctx.From = labels.LabelArray{
   530  		labels.NewLabel("foo2", "bar2", labels.LabelSourceK8s),
   531  	}
   532  
   533  	// ctx.From needs to have all labels from the policy in order to be accepted
   534  	c.Assert(repo.AllowsEgressRLocked(&ctx), Not(Equals), api.Allowed)
   535  
   536  	ctx = policy.SearchContext{
   537  		To: labels.LabelArray{
   538  			labels.NewLabel("foo3", "bar3", labels.LabelSourceK8s),
   539  		},
   540  		From: labels.LabelArray{
   541  			labels.NewLabel("foo1", "bar1", labels.LabelSourceK8s),
   542  			labels.NewLabel("foo2", "bar2", labels.LabelSourceK8s),
   543  		},
   544  		Trace: policy.TRACE_VERBOSE,
   545  	}
   546  
   547  	// ctx.To also needs to have all labels from the policy in order to be accepted.
   548  	c.Assert(repo.AllowsEgressRLocked(&ctx), Not(Equals), api.Allowed)
   549  }
   550  
   551  func parseAndAddRules(c *C, p *networkingv1.NetworkPolicy) *policy.Repository {
   552  	repo := testNewPolicyRepository()
   553  	rules, err := ParseNetworkPolicy(p)
   554  	c.Assert(err, IsNil)
   555  	rev := repo.GetRevision()
   556  	_, id := repo.AddList(rules)
   557  	c.Assert(id, Equals, rev+1)
   558  
   559  	return repo
   560  }
   561  
   562  func (s *K8sSuite) TestParseNetworkPolicyEgressAllowAll(c *C) {
   563  	repo := parseAndAddRules(c, &networkingv1.NetworkPolicy{
   564  		Spec: networkingv1.NetworkPolicySpec{
   565  			PodSelector: labelSelectorA,
   566  			Egress: []networkingv1.NetworkPolicyEgressRule{
   567  				{
   568  					To: []networkingv1.NetworkPolicyPeer{},
   569  				},
   570  			},
   571  		},
   572  	})
   573  
   574  	c.Assert(repo.AllowsEgressRLocked(&ctxAToB), Equals, api.Allowed)
   575  	c.Assert(repo.AllowsEgressRLocked(&ctxAToC), Equals, api.Allowed)
   576  
   577  	ctxAToC80 := ctxAToC
   578  	ctxAToC80.DPorts = []*models.Port{{Port: 80, Protocol: models.PortProtocolTCP}}
   579  	c.Assert(repo.AllowsEgressRLocked(&ctxAToC80), Equals, api.Allowed)
   580  
   581  	ctxAToC90 := ctxAToC
   582  	ctxAToC90.DPorts = []*models.Port{{Port: 90, Protocol: models.PortProtocolTCP}}
   583  	c.Assert(repo.AllowsEgressRLocked(&ctxAToC90), Equals, api.Allowed)
   584  }
   585  
   586  func (s *K8sSuite) TestParseNetworkPolicyEgressL4AllowAll(c *C) {
   587  	repo := parseAndAddRules(c, &networkingv1.NetworkPolicy{
   588  		Spec: networkingv1.NetworkPolicySpec{
   589  			PodSelector: labelSelectorA,
   590  			Egress: []networkingv1.NetworkPolicyEgressRule{
   591  				{
   592  					Ports: []networkingv1.NetworkPolicyPort{port80},
   593  					To:    []networkingv1.NetworkPolicyPeer{},
   594  				},
   595  			},
   596  		},
   597  	})
   598  
   599  	ctxAToC80 := ctxAToC
   600  	ctxAToC80.DPorts = []*models.Port{{Port: 80, Protocol: models.PortProtocolTCP}}
   601  	c.Assert(repo.AllowsEgressRLocked(&ctxAToC80), Equals, api.Allowed)
   602  
   603  	ctxAToC90 := ctxAToC
   604  	ctxAToC90.DPorts = []*models.Port{{Port: 90, Protocol: models.PortProtocolTCP}}
   605  	c.Assert(repo.AllowsEgressRLocked(&ctxAToC90), Equals, api.Denied)
   606  }
   607  
   608  func (s *K8sSuite) TestParseNetworkPolicyIngressAllowAll(c *C) {
   609  	repo := parseAndAddRules(c, &networkingv1.NetworkPolicy{
   610  		Spec: networkingv1.NetworkPolicySpec{
   611  			PodSelector: labelSelectorC,
   612  			Ingress: []networkingv1.NetworkPolicyIngressRule{
   613  				{
   614  					From: []networkingv1.NetworkPolicyPeer{},
   615  				},
   616  			},
   617  		},
   618  	})
   619  
   620  	c.Assert(repo.AllowsIngressRLocked(&ctxAToB), Equals, api.Denied)
   621  	c.Assert(repo.AllowsIngressRLocked(&ctxAToC), Equals, api.Allowed)
   622  
   623  	ctxAToC80 := ctxAToC
   624  	ctxAToC80.DPorts = []*models.Port{{Port: 80, Protocol: models.PortProtocolTCP}}
   625  	c.Assert(repo.AllowsIngressRLocked(&ctxAToC80), Equals, api.Allowed)
   626  
   627  	ctxAToC90 := ctxAToC
   628  	ctxAToC90.DPorts = []*models.Port{{Port: 90, Protocol: models.PortProtocolTCP}}
   629  	c.Assert(repo.AllowsIngressRLocked(&ctxAToC90), Equals, api.Allowed)
   630  }
   631  
   632  func (s *K8sSuite) TestParseNetworkPolicyIngressL4AllowAll(c *C) {
   633  	repo := parseAndAddRules(c, &networkingv1.NetworkPolicy{
   634  		Spec: networkingv1.NetworkPolicySpec{
   635  			PodSelector: labelSelectorC,
   636  			Ingress: []networkingv1.NetworkPolicyIngressRule{
   637  				{
   638  					Ports: []networkingv1.NetworkPolicyPort{port80},
   639  					From:  []networkingv1.NetworkPolicyPeer{},
   640  				},
   641  			},
   642  		},
   643  	})
   644  
   645  	c.Assert(repo.AllowsIngressRLocked(&ctxAToB), Equals, api.Denied)
   646  
   647  	ctxAToC80 := ctxAToC
   648  	ctxAToC80.DPorts = []*models.Port{{Port: 80, Protocol: models.PortProtocolTCP}}
   649  	c.Assert(repo.AllowsIngressRLocked(&ctxAToC80), Equals, api.Allowed)
   650  
   651  	ctxAToC90 := ctxAToC
   652  	ctxAToC90.DPorts = []*models.Port{{Port: 90, Protocol: models.PortProtocolTCP}}
   653  	c.Assert(repo.AllowsIngressRLocked(&ctxAToC90), Equals, api.Denied)
   654  }
   655  
   656  func (s *K8sSuite) TestParseNetworkPolicyUnknownProto(c *C) {
   657  	netPolicy := &networkingv1.NetworkPolicy{
   658  		Spec: networkingv1.NetworkPolicySpec{
   659  			Ingress: []networkingv1.NetworkPolicyIngressRule{
   660  				{
   661  					Ports: []networkingv1.NetworkPolicyPort{
   662  						{
   663  							Port: &intstr.IntOrString{
   664  								Type:   intstr.String,
   665  								StrVal: "unknown",
   666  							},
   667  						},
   668  					},
   669  				},
   670  			},
   671  		},
   672  	}
   673  
   674  	rules, err := ParseNetworkPolicy(netPolicy)
   675  	c.Assert(err, Not(IsNil))
   676  	c.Assert(len(rules), Equals, 0)
   677  }
   678  
   679  func (s *K8sSuite) TestParseNetworkPolicyEmptyFrom(c *C) {
   680  	// From missing, all sources should be allowed
   681  	netPolicy1 := &networkingv1.NetworkPolicy{
   682  		Spec: networkingv1.NetworkPolicySpec{
   683  			PodSelector: metav1.LabelSelector{
   684  				MatchLabels: map[string]string{
   685  					"foo1": "bar1",
   686  				},
   687  			},
   688  			Ingress: []networkingv1.NetworkPolicyIngressRule{
   689  				{},
   690  			},
   691  		},
   692  	}
   693  
   694  	rules, err := ParseNetworkPolicy(netPolicy1)
   695  	c.Assert(err, IsNil)
   696  	c.Assert(len(rules), Equals, 1)
   697  
   698  	ctx := policy.SearchContext{
   699  		From: labels.LabelArray{
   700  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
   701  			labels.NewLabel("foo0", "bar0", labels.LabelSourceK8s),
   702  		},
   703  		To: labels.LabelArray{
   704  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
   705  			labels.NewLabel("foo1", "bar1", labels.LabelSourceK8s),
   706  		},
   707  		Trace: policy.TRACE_VERBOSE,
   708  	}
   709  
   710  	repo := testNewPolicyRepository()
   711  	repo.AddList(rules)
   712  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Allowed)
   713  
   714  	// Empty From rules, all sources should be allowed
   715  	netPolicy2 := &networkingv1.NetworkPolicy{
   716  		Spec: networkingv1.NetworkPolicySpec{
   717  			PodSelector: metav1.LabelSelector{
   718  				MatchLabels: map[string]string{
   719  					"foo1": "bar1",
   720  				},
   721  			},
   722  			Ingress: []networkingv1.NetworkPolicyIngressRule{
   723  				{
   724  					From:  []networkingv1.NetworkPolicyPeer{},
   725  					Ports: []networkingv1.NetworkPolicyPort{},
   726  				},
   727  			},
   728  		},
   729  	}
   730  
   731  	rules, err = ParseNetworkPolicy(netPolicy2)
   732  	c.Assert(err, IsNil)
   733  	c.Assert(len(rules), Equals, 1)
   734  	repo = testNewPolicyRepository()
   735  	repo.AddList(rules)
   736  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Allowed)
   737  }
   738  
   739  func (s *K8sSuite) TestParseNetworkPolicyDenyAll(c *C) {
   740  	// From missing, all sources should be allowed
   741  	netPolicy1 := &networkingv1.NetworkPolicy{
   742  		Spec: networkingv1.NetworkPolicySpec{
   743  			PodSelector: metav1.LabelSelector{
   744  				MatchLabels: map[string]string{},
   745  			},
   746  		},
   747  	}
   748  
   749  	rules, err := ParseNetworkPolicy(netPolicy1)
   750  	c.Assert(err, IsNil)
   751  	c.Assert(len(rules), Equals, 1)
   752  
   753  	ctx := policy.SearchContext{
   754  		From: labels.LabelArray{
   755  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
   756  			labels.NewLabel("foo0", "bar0", labels.LabelSourceK8s),
   757  		},
   758  		To: labels.LabelArray{
   759  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
   760  			labels.NewLabel("foo1", "bar1", labels.LabelSourceK8s),
   761  		},
   762  		Trace: policy.TRACE_VERBOSE,
   763  	}
   764  
   765  	repo := testNewPolicyRepository()
   766  	repo.AddList(rules)
   767  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Denied)
   768  }
   769  
   770  func (s *K8sSuite) TestParseNetworkPolicyNoIngress(c *C) {
   771  	netPolicy := &networkingv1.NetworkPolicy{
   772  		Spec: networkingv1.NetworkPolicySpec{
   773  			PodSelector: metav1.LabelSelector{
   774  				MatchLabels: map[string]string{
   775  					"foo1": "bar1",
   776  					"foo2": "bar2",
   777  				},
   778  			},
   779  		},
   780  	}
   781  
   782  	rules, err := ParseNetworkPolicy(netPolicy)
   783  	c.Assert(err, IsNil)
   784  	c.Assert(len(rules), Equals, 1)
   785  }
   786  
   787  func (s *K8sSuite) TestNetworkPolicyExamples(c *C) {
   788  	// Example 1a: Only allow traffic from frontend pods on TCP port 6379 to
   789  	// backend pods in the same namespace `myns`
   790  	ex1 := []byte(`{
   791    "kind": "NetworkPolicy",
   792    "apiVersion": "extensions/v1beta1",
   793    "metadata": {
   794      "name": "allow-frontend",
   795      "namespace": "myns"
   796    },
   797    "spec": {
   798      "podSelector": {
   799        "matchLabels": {
   800          "role": "backend"
   801        }
   802      },
   803      "ingress": [
   804        {
   805          "from": [
   806            {
   807              "podSelector": {
   808                "matchLabels": {
   809                  "role": "frontend"
   810                }
   811              }
   812            }
   813          ],
   814          "ports": [
   815            {
   816              "protocol": "TCP",
   817              "port": 6379
   818            }
   819          ]
   820        }
   821      ]
   822    }
   823  }`)
   824  	np := networkingv1.NetworkPolicy{}
   825  	err := json.Unmarshal(ex1, &np)
   826  	c.Assert(err, IsNil)
   827  
   828  	_, err = ParseNetworkPolicy(&np)
   829  	c.Assert(err, IsNil)
   830  
   831  	// Example 1b: Only allow traffic from frontend pods to backend pods
   832  	// in the same namespace `myns`
   833  	ex1 = []byte(`{
   834    "kind": "NetworkPolicy",
   835    "apiVersion": "extensions/networkingv1",
   836    "metadata": {
   837      "name": "allow-frontend",
   838      "namespace": "myns"
   839    },
   840    "spec": {
   841      "podSelector": {
   842        "matchLabels": {
   843          "role": "backend"
   844        }
   845      },
   846      "ingress": [
   847        {
   848          "from": [
   849            {
   850              "podSelector": {
   851                "matchLabels": {
   852                  "role": "frontend"
   853                }
   854              }
   855            }
   856          ]
   857        },{
   858          "ports": [
   859            {
   860              "protocol": "TCP",
   861              "port": 6379
   862            }
   863          ]
   864        }
   865      ]
   866    }
   867  }`)
   868  	np = networkingv1.NetworkPolicy{}
   869  	err = json.Unmarshal(ex1, &np)
   870  	c.Assert(err, IsNil)
   871  
   872  	rules, err := ParseNetworkPolicy(&np)
   873  	c.Assert(err, IsNil)
   874  	c.Assert(len(rules), Equals, 1)
   875  
   876  	repo := testNewPolicyRepository()
   877  	repo.AddList(rules)
   878  	ctx := policy.SearchContext{
   879  		From: labels.LabelArray{
   880  			labels.NewLabel(k8sConst.PodNamespaceLabel, "myns", labels.LabelSourceK8s),
   881  			labels.NewLabel("role", "frontend", labels.LabelSourceK8s),
   882  		},
   883  		To: labels.LabelArray{
   884  			labels.NewLabel("role", "backend", labels.LabelSourceK8s),
   885  		},
   886  		Trace: policy.TRACE_VERBOSE,
   887  	}
   888  	// Doesn't share the same namespace
   889  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Denied)
   890  
   891  	ctx = policy.SearchContext{
   892  		From: labels.LabelArray{
   893  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
   894  			labels.NewLabel("role", "frontend", labels.LabelSourceK8s),
   895  		},
   896  		To: labels.LabelArray{
   897  			labels.NewLabel("role", "backend", labels.LabelSourceK8s),
   898  		},
   899  		Trace: policy.TRACE_VERBOSE,
   900  	}
   901  	// Doesn't share the same namespace
   902  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Denied)
   903  
   904  	ctx = policy.SearchContext{
   905  		From: labels.LabelArray{
   906  			labels.NewLabel(k8sConst.PodNamespaceLabel, "myns", labels.LabelSourceK8s),
   907  			labels.NewLabel("role", "frontend", labels.LabelSourceK8s),
   908  		},
   909  		To: labels.LabelArray{
   910  			labels.NewLabel(k8sConst.PodNamespaceLabel, "myns", labels.LabelSourceK8s),
   911  			labels.NewLabel("role", "backend", labels.LabelSourceK8s),
   912  		},
   913  		DPorts: []*models.Port{
   914  			{
   915  				Port:     6379,
   916  				Protocol: models.PortProtocolTCP,
   917  			},
   918  		},
   919  		Trace: policy.TRACE_VERBOSE,
   920  	}
   921  	// Should be ACCEPT sense the traffic needs to come from `frontend` AND
   922  	// port 6379 and belong to the same namespace `myns`.
   923  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Allowed)
   924  
   925  	// Example 2a: Allow TCP 443 from any source in Bob's namespaces.
   926  	ex2 := []byte(`{
   927    "kind": "NetworkPolicy",
   928    "apiVersion": "extensions/v1beta1",
   929    "metadata": {
   930      "name": "allow-tcp-443"
   931    },
   932    "spec": {
   933      "podSelector": {
   934        "matchLabels": {
   935          "role": "frontend"
   936        }
   937      },
   938      "ingress": [
   939        {
   940          "ports": [
   941            {
   942              "protocol": "TCP",
   943              "port": 443
   944            }
   945          ],
   946          "from": [
   947            {
   948              "namespaceSelector": {
   949                "matchLabels": {
   950                  "user": "bob"
   951                }
   952              }
   953            }
   954          ]
   955        }
   956      ]
   957    }
   958  }`)
   959  
   960  	np = networkingv1.NetworkPolicy{}
   961  	err = json.Unmarshal(ex2, &np)
   962  	c.Assert(err, IsNil)
   963  
   964  	_, err = ParseNetworkPolicy(&np)
   965  	c.Assert(err, IsNil)
   966  
   967  	// Example 2b: Allow from any source in Bob's namespaces.
   968  	ex2 = []byte(`{
   969    "kind": "NetworkPolicy",
   970    "apiVersion": "extensions/networkingv1",
   971    "metadata": {
   972      "name": "allow-tcp-443"
   973    },
   974    "spec": {
   975      "podSelector": {
   976        "matchLabels": {
   977          "role": "frontend"
   978        }
   979      },
   980      "ingress": [
   981        {
   982          "ports": [
   983            {
   984              "protocol": "TCP",
   985              "port": 443
   986            }
   987          ],
   988          "from": [
   989            {
   990              "namespaceSelector": {
   991                "matchLabels": {
   992                  "user": "bob"
   993                }
   994              }
   995            }
   996          ]
   997        }
   998      ]
   999    }
  1000  }`)
  1001  
  1002  	np = networkingv1.NetworkPolicy{}
  1003  	err = json.Unmarshal(ex2, &np)
  1004  	c.Assert(err, IsNil)
  1005  
  1006  	rules, err = ParseNetworkPolicy(&np)
  1007  	c.Assert(err, IsNil)
  1008  	c.Assert(len(rules), Equals, 1)
  1009  
  1010  	repo = testNewPolicyRepository()
  1011  	repo.AddList(rules)
  1012  	ctx = policy.SearchContext{
  1013  		From: labels.LabelArray{
  1014  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
  1015  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "user"), "bob", labels.LabelSourceK8s),
  1016  		},
  1017  		To: labels.LabelArray{
  1018  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
  1019  			labels.NewLabel("role", "frontend", labels.LabelSourceK8s),
  1020  		},
  1021  		Trace: policy.TRACE_VERBOSE,
  1022  	}
  1023  
  1024  	// Should be DENY sense the traffic needs to come from
  1025  	// namespace `user=bob` AND port 443.
  1026  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Denied)
  1027  
  1028  	l4Policy, err := repo.ResolveL4IngressPolicy(&ctx)
  1029  	c.Assert(l4Policy, Not(IsNil))
  1030  	c.Assert(err, IsNil)
  1031  	l4Policy.Detach(repo.GetSelectorCache())
  1032  
  1033  	ctx = policy.SearchContext{
  1034  		From: labels.LabelArray{
  1035  			labels.NewLabel(k8sConst.PodNamespaceLabel, "myns", labels.LabelSourceK8s),
  1036  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "user"), "bob", labels.LabelSourceK8s),
  1037  		},
  1038  		DPorts: []*models.Port{
  1039  			{
  1040  				Port:     443,
  1041  				Protocol: models.PortProtocolTCP,
  1042  			},
  1043  		},
  1044  		To: labels.LabelArray{
  1045  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
  1046  			labels.NewLabel("role", "frontend", labels.LabelSourceK8s),
  1047  		},
  1048  		Trace: policy.TRACE_VERBOSE,
  1049  	}
  1050  	// Should be ACCEPT sense the traffic comes from Bob's namespaces
  1051  	// (even if it's a different namespace than `default`) AND port 443.
  1052  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Allowed)
  1053  
  1054  	// Example 3: Allow all traffic to all pods in this namespace.
  1055  	ex3 := []byte(`{
  1056    "kind": "NetworkPolicy",
  1057    "apiVersion": "extensions/v1beta1",
  1058    "metadata": {
  1059      "name": "allow-all"
  1060    },
  1061    "spec": {
  1062      "podSelector": null,
  1063      "ingress": [
  1064        {
  1065        }
  1066      ]
  1067    }
  1068  }`)
  1069  
  1070  	np = networkingv1.NetworkPolicy{}
  1071  	err = json.Unmarshal(ex3, &np)
  1072  	c.Assert(err, IsNil)
  1073  
  1074  	rules, err = ParseNetworkPolicy(&np)
  1075  	c.Assert(err, IsNil)
  1076  	c.Assert(len(rules), Equals, 1)
  1077  
  1078  	repo = testNewPolicyRepository()
  1079  	repo.AddList(rules)
  1080  	ctx = policy.SearchContext{
  1081  		From: labels.LabelArray{
  1082  			labels.NewLabel(k8sConst.PodNamespaceLabel, "myns", labels.LabelSourceK8s),
  1083  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "user"), "bob", labels.LabelSourceK8s),
  1084  		},
  1085  		To: labels.LabelArray{
  1086  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
  1087  			labels.NewLabel("role", "backend", labels.LabelSourceK8s),
  1088  		},
  1089  		Trace: policy.TRACE_VERBOSE,
  1090  	}
  1091  	// Should be ACCEPT since it's going to `default` namespace
  1092  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Allowed)
  1093  
  1094  	ctx = policy.SearchContext{
  1095  		From: labels.LabelArray{
  1096  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
  1097  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "user"), "bob", labels.LabelSourceK8s),
  1098  		},
  1099  		To: labels.LabelArray{
  1100  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
  1101  			labels.NewLabel("role", "backend", labels.LabelSourceK8s),
  1102  		},
  1103  		Trace: policy.TRACE_VERBOSE,
  1104  	}
  1105  	// Should be ACCEPT since it's coming from `default` and going to `default` ns
  1106  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Allowed)
  1107  
  1108  	ctx = policy.SearchContext{
  1109  		From: labels.LabelArray{
  1110  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
  1111  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "user"), "bob", labels.LabelSourceK8s),
  1112  		},
  1113  		To: labels.LabelArray{
  1114  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
  1115  			labels.NewLabel("role", "backend", labels.LabelSourceK8s),
  1116  		},
  1117  		DPorts: []*models.Port{
  1118  			{
  1119  				Port:     443,
  1120  				Protocol: models.PortProtocolTCP,
  1121  			},
  1122  		},
  1123  		Trace: policy.TRACE_VERBOSE,
  1124  	}
  1125  	// Should be ACCEPT since it's coming from `default` and going to `default` namespace.
  1126  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Allowed)
  1127  
  1128  	// Example 4a: Example 4 is similar to example 2 but we will add both network
  1129  	// policies to see if the rules are additive for the same podSelector.
  1130  	ex4 := []byte(`{
  1131    "kind": "NetworkPolicy",
  1132    "apiVersion": "extensions/v1beta1",
  1133    "metadata": {
  1134      "name": "allow-tcp-8080"
  1135    },
  1136    "spec": {
  1137      "podSelector": {
  1138        "matchLabels": {
  1139          "role": "frontend"
  1140        }
  1141      },
  1142      "ingress": [
  1143        {
  1144          "ports": [
  1145            {
  1146              "protocol": "UDP",
  1147              "port": 8080
  1148            }
  1149          ],
  1150          "from": [
  1151            {
  1152              "namespaceSelector": {
  1153                "matchLabels": {
  1154                  "user": "bob"
  1155                }
  1156              }
  1157            }
  1158          ]
  1159        }
  1160      ]
  1161    }
  1162  }`)
  1163  
  1164  	np = networkingv1.NetworkPolicy{}
  1165  	err = json.Unmarshal(ex4, &np)
  1166  	c.Assert(err, IsNil)
  1167  
  1168  	rules, err = ParseNetworkPolicy(&np)
  1169  	c.Assert(err, IsNil)
  1170  	c.Assert(len(rules), Equals, 1)
  1171  
  1172  	// Example 4b: Example 4 is similar to example 2 but we will add both network
  1173  	// policies to see if the rules are additive for the same podSelector.
  1174  	ex4 = []byte(`{
  1175    "kind": "NetworkPolicy",
  1176    "apiVersion": "extensions/networkingv1",
  1177    "metadata": {
  1178      "name": "allow-tcp-8080"
  1179    },
  1180    "spec": {
  1181      "podSelector": {
  1182        "matchLabels": {
  1183          "role": "frontend"
  1184        }
  1185      },
  1186      "ingress": [
  1187        {
  1188          "ports": [
  1189            {
  1190              "protocol": "UDP",
  1191              "port": 8080
  1192            }
  1193          ]
  1194        },{
  1195          "from": [
  1196            {
  1197              "namespaceSelector": {
  1198                "matchLabels": {
  1199                  "user": "bob"
  1200                }
  1201              }
  1202            }
  1203          ]
  1204        }
  1205      ]
  1206    }
  1207  }`)
  1208  
  1209  	np = networkingv1.NetworkPolicy{}
  1210  	err = json.Unmarshal(ex4, &np)
  1211  	c.Assert(err, IsNil)
  1212  
  1213  	rules, err = ParseNetworkPolicy(&np)
  1214  	c.Assert(err, IsNil)
  1215  	c.Assert(len(rules), Equals, 1)
  1216  
  1217  	repo = testNewPolicyRepository()
  1218  	// add example 4
  1219  	repo.AddList(rules)
  1220  
  1221  	np = networkingv1.NetworkPolicy{}
  1222  	err = json.Unmarshal(ex2, &np)
  1223  	c.Assert(err, IsNil)
  1224  
  1225  	rules, err = ParseNetworkPolicy(&np)
  1226  	c.Assert(err, IsNil)
  1227  	// add example 2
  1228  	repo.AddList(rules)
  1229  
  1230  	ctx = policy.SearchContext{
  1231  		From: labels.LabelArray{
  1232  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
  1233  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "user"), "bob", labels.LabelSourceK8s),
  1234  		},
  1235  		DPorts: []*models.Port{
  1236  			{
  1237  				Protocol: models.PortProtocolUDP,
  1238  				Port:     8080,
  1239  			},
  1240  		},
  1241  		To: labels.LabelArray{
  1242  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
  1243  			labels.NewLabel("role", "frontend", labels.LabelSourceK8s),
  1244  		},
  1245  		Trace: policy.TRACE_VERBOSE,
  1246  	}
  1247  	// Should be ACCEPT sense traffic comes from Bob's namespaces AND port 8080 as specified in `ex4`.
  1248  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Allowed)
  1249  
  1250  	ctx = policy.SearchContext{
  1251  		From: labels.LabelArray{
  1252  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
  1253  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "user"), "bob", labels.LabelSourceK8s),
  1254  		},
  1255  		DPorts: []*models.Port{
  1256  			{
  1257  				Port:     443,
  1258  				Protocol: models.PortProtocolTCP,
  1259  			},
  1260  		},
  1261  		To: labels.LabelArray{
  1262  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
  1263  			labels.NewLabel("role", "frontend", labels.LabelSourceK8s),
  1264  		},
  1265  		Trace: policy.TRACE_VERBOSE,
  1266  	}
  1267  	// Should be ACCEPT sense traffic comes from Bob's namespaces AND port 443 as specified in `ex2`.
  1268  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Allowed)
  1269  
  1270  	ctx = policy.SearchContext{
  1271  		From: labels.LabelArray{
  1272  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
  1273  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "user"), "alice", labels.LabelSourceK8s),
  1274  		},
  1275  		DPorts: []*models.Port{
  1276  			{
  1277  				Protocol: models.PortProtocolUDP,
  1278  				Port:     8080,
  1279  			},
  1280  		},
  1281  		To: labels.LabelArray{
  1282  			labels.NewLabel(k8sConst.PodNamespaceLabel, v1.NamespaceDefault, labels.LabelSourceK8s),
  1283  			labels.NewLabel("role", "frontend", labels.LabelSourceK8s),
  1284  		},
  1285  		Trace: policy.TRACE_VERBOSE,
  1286  	}
  1287  	// Should be ACCEPT despite coming from Alice's namespaces since it's port 8080 as specified in `ex4`.
  1288  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Allowed)
  1289  
  1290  	// Example 5: Some policies with match expressions.
  1291  	ex5 := []byte(`{
  1292    "kind": "NetworkPolicy",
  1293    "apiVersion": "extensions/v1beta1",
  1294    "metadata": {
  1295      "name": "allow-tcp-8080",
  1296      "namespace": "expressions"
  1297    },
  1298    "spec": {
  1299      "podSelector": {
  1300        "matchLabels": {
  1301          "component": "redis"
  1302        },
  1303        "matchExpressions": [
  1304          {
  1305            "key": "tier",
  1306            "operator": "In",
  1307            "values": [
  1308              "cache"
  1309            ]
  1310          },
  1311          {
  1312            "key": "environment",
  1313            "operator": "NotIn",
  1314            "values": [
  1315              "dev"
  1316            ]
  1317          }
  1318        ]
  1319      },
  1320      "ingress": [
  1321        {
  1322          "ports": [
  1323            {
  1324              "protocol": "UDP",
  1325              "port": 8080
  1326            }
  1327          ],
  1328          "from": [
  1329            {
  1330              "namespaceSelector": {
  1331                "matchLabels": {
  1332                  "component": "redis"
  1333                },
  1334                "matchExpressions": [
  1335                  {
  1336                    "key": "tier",
  1337                    "operator": "In",
  1338                    "values": [
  1339                      "cache"
  1340                    ]
  1341                  },
  1342                  {
  1343                    "key": "environment",
  1344                    "operator": "NotIn",
  1345                    "values": [
  1346                      "dev"
  1347                    ]
  1348                  }
  1349                ]
  1350              }
  1351            }
  1352          ]
  1353        }
  1354      ]
  1355    }
  1356  }`)
  1357  
  1358  	np = networkingv1.NetworkPolicy{}
  1359  	err = json.Unmarshal(ex5, &np)
  1360  	c.Assert(err, IsNil)
  1361  
  1362  	rules, err = ParseNetworkPolicy(&np)
  1363  	c.Assert(err, IsNil)
  1364  	c.Assert(len(rules), Equals, 1)
  1365  	repo.AddList(rules)
  1366  
  1367  	// A reminder: from the kubernetes network policy spec:
  1368  	// namespaceSelector:
  1369  	//  Selects Namespaces using cluster scoped-labels.  This
  1370  	//  matches all pods in all namespaces selected by this label selector.
  1371  	//  This field follows standard label selector semantics.
  1372  	//  If omitted, this selector selects no namespaces.
  1373  	//  If present but empty, this selector selects all namespaces.
  1374  	ctx = policy.SearchContext{
  1375  		From: labels.LabelArray{
  1376  			// doesn't matter the namespace.
  1377  			labels.NewLabel(k8sConst.PodNamespaceLabel, "myns", labels.LabelSourceK8s),
  1378  			// component==redis is in the policy
  1379  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "component"), "redis", labels.LabelSourceK8s),
  1380  			// tier==cache is in the policy
  1381  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "tier"), "cache", labels.LabelSourceK8s),
  1382  			// environment is not in `dev` which is in the policy
  1383  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "environment"), "production", labels.LabelSourceK8s),
  1384  			// doesn't matter, there isn't any matchExpression denying traffic from any zone.
  1385  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "zone"), "eu-1", labels.LabelSourceK8s),
  1386  		},
  1387  		DPorts: []*models.Port{
  1388  			{
  1389  				Port:     8080,
  1390  				Protocol: models.PortProtocolUDP,
  1391  			},
  1392  		},
  1393  		To: labels.LabelArray{
  1394  			// Namespace needs to be in `expressions` since the policy is being enforced for that namespace.
  1395  			labels.NewLabel(k8sConst.PodNamespaceLabel, "expressions", labels.LabelSourceK8s),
  1396  			// component==redis is in the policy.
  1397  			labels.NewLabel("component", "redis", labels.LabelSourceK8s),
  1398  			// tier==cache is in the policy
  1399  			labels.NewLabel("tier", "cache", labels.LabelSourceK8s),
  1400  		},
  1401  		Trace: policy.TRACE_VERBOSE,
  1402  	}
  1403  	// Should be ACCEPT since the SearchContext is being covered by the rules.
  1404  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Allowed)
  1405  
  1406  	ctx.To = labels.LabelArray{
  1407  		// Namespace needs to be in `expressions` since the policy is being enforced for that namespace.
  1408  		labels.NewLabel(k8sConst.PodNamespaceLabel, "myns", labels.LabelSourceK8s),
  1409  		// component==redis is in the policy.
  1410  		labels.NewLabel("component", "redis", labels.LabelSourceK8s),
  1411  		// tier==cache is in the policy
  1412  		labels.NewLabel("tier", "cache", labels.LabelSourceK8s),
  1413  	}
  1414  	// Should be DENY since the namespace doesn't belong to the policy.
  1415  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Denied)
  1416  
  1417  	ctx = policy.SearchContext{
  1418  		From: labels.LabelArray{
  1419  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "component"), "redis", labels.LabelSourceK8s),
  1420  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "tier"), "cache", labels.LabelSourceK8s),
  1421  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "environment"), "dev", labels.LabelSourceK8s),
  1422  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "zone"), "eu-1", labels.LabelSourceK8s),
  1423  		},
  1424  		DPorts: []*models.Port{
  1425  			{
  1426  				Port:     8080,
  1427  				Protocol: models.PortProtocolUDP,
  1428  			},
  1429  		},
  1430  		To: labels.LabelArray{
  1431  			labels.NewLabel(k8sConst.PodNamespaceLabel, "expressions", labels.LabelSourceK8s),
  1432  			labels.NewLabel("component", "redis", labels.LabelSourceK8s),
  1433  			labels.NewLabel("tier", "cache", labels.LabelSourceK8s),
  1434  		},
  1435  		Trace: policy.TRACE_VERBOSE,
  1436  	}
  1437  	// Should be DENY since the environment is from dev.
  1438  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Denied)
  1439  
  1440  	ctx = policy.SearchContext{
  1441  		From: labels.LabelArray{
  1442  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "component"), "redis", labels.LabelSourceK8s),
  1443  			labels.NewLabel(policy.JoinPath(k8sConst.PodNamespaceMetaLabels, "tier"), "cache", labels.LabelSourceK8s),
  1444  		},
  1445  		DPorts: []*models.Port{
  1446  			{
  1447  				Port:     8080,
  1448  				Protocol: models.PortProtocolUDP,
  1449  			},
  1450  		},
  1451  		To: labels.LabelArray{
  1452  			labels.NewLabel(k8sConst.PodNamespaceLabel, "expressions", labels.LabelSourceK8s),
  1453  			labels.NewLabel("component", "redis", labels.LabelSourceK8s),
  1454  			labels.NewLabel("tier", "cache", labels.LabelSourceK8s),
  1455  		},
  1456  		Trace: policy.TRACE_VERBOSE,
  1457  	}
  1458  	// Should be ACCEPT since the environment is from dev.
  1459  	c.Assert(repo.AllowsIngressRLocked(&ctx), Equals, api.Allowed)
  1460  }
  1461  
  1462  func (s *K8sSuite) TestCIDRPolicyExamples(c *C) {
  1463  	ex1 := []byte(`{
  1464    "kind": "NetworkPolicy",
  1465    "apiVersion": "extensions/networkingv1",
  1466    "metadata": {
  1467      "name": "ingress-cidr-test",
  1468      "namespace": "myns"
  1469    },
  1470    "spec": {
  1471      "podSelector": {
  1472        "matchLabels": {
  1473          "role": "backend"
  1474        }
  1475      },
  1476      "ingress": [
  1477        {
  1478          "from": [
  1479            {
  1480              "namespaceSelector": {
  1481                "matchLabels": {
  1482                  "user": "bob"
  1483                }
  1484              }
  1485            }
  1486          ]
  1487        }, {
  1488          "from": [
  1489            {
  1490              "ipBlock": {
  1491                "cidr": "10.0.0.0/8",
  1492  	          "except": [
  1493  	            "10.96.0.0/12"
  1494  	          ]
  1495              }
  1496            }
  1497          ]
  1498        }
  1499      ]
  1500    }
  1501  }`)
  1502  	np := networkingv1.NetworkPolicy{}
  1503  	err := json.Unmarshal(ex1, &np)
  1504  	c.Assert(err, IsNil)
  1505  
  1506  	rules, err := ParseNetworkPolicy(&np)
  1507  	c.Assert(err, IsNil)
  1508  	c.Assert(rules, NotNil)
  1509  	c.Assert(len(rules), Equals, 1)
  1510  	c.Assert(len(rules[0].Ingress), Equals, 2)
  1511  
  1512  	ex2 := []byte(`{
  1513    "kind": "NetworkPolicy",
  1514    "apiVersion": "extensions/networkingv1",
  1515    "metadata": {
  1516      "name": "ingress-cidr-test",
  1517      "namespace": "myns"
  1518    },
  1519    "spec": {
  1520      "podSelector": {
  1521        "matchLabels": {
  1522          "role": "backend"
  1523        }
  1524      },
  1525      "egress": [
  1526        {
  1527          "to": [
  1528            {
  1529              "ipBlock": {
  1530                "cidr": "10.0.0.0/8",
  1531  	          "except": [
  1532  	            "10.96.0.0/12", "10.255.255.254/32"
  1533  	          ]
  1534              }
  1535            },
  1536  	      {
  1537              "ipBlock": {
  1538                "cidr": "11.0.0.0/8",
  1539  	          "except": [
  1540  	            "11.96.0.0/12", "11.255.255.254/32"
  1541  	          ]
  1542              }
  1543            }
  1544          ]
  1545        }
  1546      ]
  1547    }
  1548  }`)
  1549  
  1550  	np = networkingv1.NetworkPolicy{}
  1551  	err = json.Unmarshal(ex2, &np)
  1552  	c.Assert(err, IsNil)
  1553  
  1554  	rules, err = ParseNetworkPolicy(&np)
  1555  	c.Assert(err, IsNil)
  1556  	c.Assert(rules, NotNil)
  1557  	c.Assert(len(rules), Equals, 1)
  1558  	c.Assert(rules[0].Egress[0].ToCIDRSet[0].Cidr, Equals, api.CIDR("10.0.0.0/8"))
  1559  
  1560  	expectedCIDRs := []api.CIDR{"10.96.0.0/12", "10.255.255.254/32"}
  1561  	for k, v := range rules[0].Egress[0].ToCIDRSet[0].ExceptCIDRs {
  1562  		c.Assert(v, Equals, expectedCIDRs[k])
  1563  	}
  1564  
  1565  	expectedCIDRs = []api.CIDR{"11.96.0.0/12", "11.255.255.254/32"}
  1566  	for k, v := range rules[0].Egress[1].ToCIDRSet[0].ExceptCIDRs {
  1567  		c.Assert(v, Equals, expectedCIDRs[k])
  1568  	}
  1569  
  1570  	c.Assert(len(rules[0].Egress), Equals, 2)
  1571  
  1572  }
  1573  
  1574  func getSelectorPointer(sel api.EndpointSelector) *api.EndpointSelector {
  1575  	return &sel
  1576  }
  1577  
  1578  func Test_parseNetworkPolicyPeer(t *testing.T) {
  1579  	type args struct {
  1580  		namespace string
  1581  		peer      *networkingv1.NetworkPolicyPeer
  1582  	}
  1583  	tests := []struct {
  1584  		name string
  1585  		args args
  1586  		want *api.EndpointSelector
  1587  	}{
  1588  		{
  1589  			name: "peer-with-pod-selector",
  1590  			args: args{
  1591  				namespace: "foo-namespace",
  1592  				peer: &networkingv1.NetworkPolicyPeer{
  1593  					PodSelector: &metav1.LabelSelector{
  1594  						MatchLabels: map[string]string{
  1595  							"foo": "bar",
  1596  						},
  1597  						MatchExpressions: []metav1.LabelSelectorRequirement{
  1598  							{
  1599  								Key:      "foo",
  1600  								Operator: metav1.LabelSelectorOpIn,
  1601  								Values:   []string{"bar", "baz"},
  1602  							},
  1603  						},
  1604  					},
  1605  				},
  1606  			},
  1607  			want: getSelectorPointer(
  1608  				api.NewESFromMatchRequirements(
  1609  					map[string]string{
  1610  						"k8s.foo":                         "bar",
  1611  						"k8s.io.kubernetes.pod.namespace": "foo-namespace",
  1612  					},
  1613  					[]metav1.LabelSelectorRequirement{
  1614  						{
  1615  							Key:      "k8s.foo",
  1616  							Operator: metav1.LabelSelectorOpIn,
  1617  							Values:   []string{"bar", "baz"},
  1618  						},
  1619  					},
  1620  				),
  1621  			),
  1622  		},
  1623  		{
  1624  			name: "peer-nil",
  1625  			args: args{
  1626  				namespace: "foo-namespace",
  1627  			},
  1628  			want: nil,
  1629  		},
  1630  		{
  1631  			name: "peer-with-pod-selector-and-ns-selector",
  1632  			args: args{
  1633  				namespace: "foo-namespace",
  1634  				peer: &networkingv1.NetworkPolicyPeer{
  1635  					PodSelector: &metav1.LabelSelector{
  1636  						MatchLabels: map[string]string{
  1637  							"foo": "bar",
  1638  						},
  1639  						MatchExpressions: []metav1.LabelSelectorRequirement{
  1640  							{
  1641  								Key:      "foo",
  1642  								Operator: metav1.LabelSelectorOpIn,
  1643  								Values:   []string{"bar", "baz"},
  1644  							},
  1645  						},
  1646  					},
  1647  					NamespaceSelector: &metav1.LabelSelector{
  1648  						MatchLabels: map[string]string{
  1649  							"ns-foo": "ns-bar",
  1650  						},
  1651  						MatchExpressions: []metav1.LabelSelectorRequirement{
  1652  							{
  1653  								Key:      "ns-foo-expression",
  1654  								Operator: metav1.LabelSelectorOpExists,
  1655  							},
  1656  						},
  1657  					},
  1658  				},
  1659  			},
  1660  			want: getSelectorPointer(
  1661  				api.NewESFromMatchRequirements(
  1662  					map[string]string{
  1663  						"k8s.foo": "bar",
  1664  						"k8s.io.cilium.k8s.namespace.labels.ns-foo": "ns-bar",
  1665  					},
  1666  					[]metav1.LabelSelectorRequirement{
  1667  						{
  1668  							Key:      "k8s.io.cilium.k8s.namespace.labels.ns-foo-expression",
  1669  							Operator: metav1.LabelSelectorOpExists,
  1670  						},
  1671  						{
  1672  							Key:      "k8s.foo",
  1673  							Operator: metav1.LabelSelectorOpIn,
  1674  							Values:   []string{"bar", "baz"},
  1675  						},
  1676  					},
  1677  				),
  1678  			),
  1679  		},
  1680  		{
  1681  			name: "peer-with-ns-selector",
  1682  			args: args{
  1683  				namespace: "foo-namespace",
  1684  				peer: &networkingv1.NetworkPolicyPeer{
  1685  					NamespaceSelector: &metav1.LabelSelector{
  1686  						MatchLabels: map[string]string{
  1687  							"ns-foo": "ns-bar",
  1688  						},
  1689  						MatchExpressions: []metav1.LabelSelectorRequirement{
  1690  							{
  1691  								Key:      "ns-foo-expression",
  1692  								Operator: metav1.LabelSelectorOpExists,
  1693  							},
  1694  						},
  1695  					},
  1696  				},
  1697  			},
  1698  			want: getSelectorPointer(
  1699  				api.NewESFromMatchRequirements(
  1700  					map[string]string{
  1701  						"k8s.io.cilium.k8s.namespace.labels.ns-foo": "ns-bar",
  1702  					},
  1703  					[]metav1.LabelSelectorRequirement{
  1704  						{
  1705  							Key:      "k8s.io.cilium.k8s.namespace.labels.ns-foo-expression",
  1706  							Operator: metav1.LabelSelectorOpExists,
  1707  						},
  1708  					},
  1709  				),
  1710  			),
  1711  		},
  1712  		{
  1713  			name: "peer-with-allow-all-ns-selector",
  1714  			args: args{
  1715  				namespace: "foo-namespace",
  1716  				peer: &networkingv1.NetworkPolicyPeer{
  1717  					NamespaceSelector: &metav1.LabelSelector{},
  1718  				},
  1719  			},
  1720  			want: getSelectorPointer(
  1721  				api.NewESFromMatchRequirements(
  1722  					map[string]string{},
  1723  					[]metav1.LabelSelectorRequirement{
  1724  						{
  1725  							Key:      fmt.Sprintf("%s.%s", labels.LabelSourceK8s, k8sConst.PodNamespaceLabel),
  1726  							Operator: metav1.LabelSelectorOpExists,
  1727  						},
  1728  					},
  1729  				),
  1730  			),
  1731  		},
  1732  	}
  1733  	for _, tt := range tests {
  1734  		t.Run(tt.name, func(t *testing.T) {
  1735  			got := parseNetworkPolicyPeer(tt.args.namespace, tt.args.peer)
  1736  			args := []interface{}{got, tt.want}
  1737  			names := []string{"obtained", "expected"}
  1738  			if equal, err := checker.DeepEquals.Check(args, names); !equal {
  1739  				t.Errorf("Failed to parseNetworkPolicyPeer():\n%s", err)
  1740  			}
  1741  		})
  1742  	}
  1743  }
  1744  
  1745  func (s *K8sSuite) TestGetPolicyLabelsv1(c *C) {
  1746  	uuid := "1bba160-ddca-11e8-b697-0800273b04ff"
  1747  	tests := []struct {
  1748  		np          *networkingv1.NetworkPolicy // input network policy
  1749  		name        string                      // expected extracted name
  1750  		namespace   string                      // expected extracted namespace
  1751  		uuid        string                      // expected extracted uuid
  1752  		derivedFrom string                      // expected extracted derived
  1753  	}{
  1754  		{
  1755  			np:          &networkingv1.NetworkPolicy{},
  1756  			name:        "",
  1757  			namespace:   v1.NamespaceDefault,
  1758  			uuid:        "",
  1759  			derivedFrom: resourceTypeNetworkPolicy,
  1760  		},
  1761  		{
  1762  			np: &networkingv1.NetworkPolicy{
  1763  				ObjectMeta: metav1.ObjectMeta{
  1764  					Annotations: map[string]string{
  1765  						annotation.Name: "foo",
  1766  					},
  1767  				},
  1768  			},
  1769  			name:        "foo",
  1770  			uuid:        "",
  1771  			namespace:   v1.NamespaceDefault,
  1772  			derivedFrom: resourceTypeNetworkPolicy,
  1773  		},
  1774  		{
  1775  			np: &networkingv1.NetworkPolicy{
  1776  				ObjectMeta: metav1.ObjectMeta{
  1777  					Name:      "foo",
  1778  					Namespace: "bar",
  1779  					UID:       types.UID(uuid),
  1780  				},
  1781  			},
  1782  			name:        "foo",
  1783  			namespace:   "bar",
  1784  			uuid:        uuid,
  1785  			derivedFrom: resourceTypeNetworkPolicy,
  1786  		},
  1787  	}
  1788  
  1789  	assertLabel := func(lbl labels.Label, key, value string) {
  1790  		c.Assert(lbl.Key, Equals, key)
  1791  		c.Assert(lbl.Value, Equals, value)
  1792  		c.Assert(lbl.Source, Equals, labels.LabelSourceK8s)
  1793  	}
  1794  
  1795  	for _, tt := range tests {
  1796  		lbls := GetPolicyLabelsv1(tt.np)
  1797  
  1798  		c.Assert(lbls, NotNil)
  1799  		c.Assert(len(lbls), Equals, 4, Commentf(
  1800  			"Incorrect number of labels: Expected DerivedFrom, Name, Namespace and UID labels."))
  1801  		assertLabel(lbls[0], "io.cilium.k8s.policy.derived-from", tt.derivedFrom)
  1802  		assertLabel(lbls[1], "io.cilium.k8s.policy.name", tt.name)
  1803  		assertLabel(lbls[2], "io.cilium.k8s.policy.namespace", tt.namespace)
  1804  		assertLabel(lbls[3], "io.cilium.k8s.policy.uid", tt.uuid)
  1805  	}
  1806  }
  1807  
  1808  func (s *K8sSuite) TestIPBlockToCIDRRule(c *C) {
  1809  	blocks := []*networkingv1.IPBlock{
  1810  		{},
  1811  		{CIDR: "192.168.1.1/24"},
  1812  		{CIDR: "192.168.1.1/24", Except: []string{}},
  1813  		{CIDR: "192.168.1.1/24", Except: []string{"192.168.1.1/28"}},
  1814  		{
  1815  			CIDR: "192.168.1.1/24",
  1816  			Except: []string{
  1817  				"192.168.1.1/30",
  1818  				"192.168.1.1/26",
  1819  				"192.168.1.1/28",
  1820  			},
  1821  		},
  1822  	}
  1823  
  1824  	for _, block := range blocks {
  1825  		cidrRule := ipBlockToCIDRRule(block)
  1826  
  1827  		exceptCIDRs := make([]api.CIDR, len(block.Except))
  1828  		for i, v := range block.Except {
  1829  			exceptCIDRs[i] = api.CIDR(v)
  1830  		}
  1831  
  1832  		c.Assert(cidrRule.Generated, Equals, false)
  1833  		c.Assert(cidrRule.Cidr, Equals, api.CIDR(block.CIDR))
  1834  
  1835  		if block.Except == nil || len(block.Except) == 0 {
  1836  			c.Assert(cidrRule.ExceptCIDRs, IsNil)
  1837  		} else {
  1838  			c.Assert(cidrRule.ExceptCIDRs, checker.DeepEquals, exceptCIDRs)
  1839  		}
  1840  	}
  1841  }