Skip to content

Commit

Permalink
Make Peer validation more comprehensive
Browse files Browse the repository at this point in the history
Signed-off-by: wgrayson <wgrayson@vmware.com>
  • Loading branch information
GraysonWu committed Dec 8, 2021
1 parent b87b76c commit 5865840
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 4 deletions.
23 changes: 19 additions & 4 deletions pkg/controller/networkpolicy/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package networkpolicy
import (
"encoding/json"
"fmt"
"reflect"
"regexp"
"strconv"
"strings"
Expand Down Expand Up @@ -461,6 +462,11 @@ func (v *antreaPolicyValidator) validateAppliedTo(ingress, egress []crdv1alpha1.
if numAppliedToInRules > 0 && (numAppliedToInRules != len(ingress)+len(egress)) {
return "appliedTo field should either be set in all rules or in none of them", false
}
for _, eachSpecAppliedTo := range specAppliedTo {
if eachSpecAppliedTo.Group != "" && numFieldsSetInPeer(eachSpecAppliedTo) > 1 {
return "group cannot be set with other peers in appliedTo", false
}
}
return "", true
}

Expand All @@ -472,10 +478,7 @@ func (v *antreaPolicyValidator) validatePeers(ingress, egress []crdv1alpha1.Rule
if peer.NamespaceSelector != nil && peer.Namespaces != nil {
return "namespaces and namespaceSelector cannot be set at the same time for a single NetworkPolicyPeer", false
}
if peer.Group == "" {
continue
}
if peer.PodSelector != nil || peer.IPBlock != nil || peer.NamespaceSelector != nil {
if peer.Group != "" && numFieldsSetInPeer(peer) > 1 {
return "group cannot be set with other peers in rules", false
}
}
Expand Down Expand Up @@ -504,6 +507,18 @@ func (v *antreaPolicyValidator) validatePeers(ingress, egress []crdv1alpha1.Rule
return "", true
}

// numFieldsSetInPeer returns the number of fields in use of a peer.
func numFieldsSetInPeer(peer crdv1alpha1.NetworkPolicyPeer) int {
num := 0
v := reflect.ValueOf(peer)
for i := 0; i < v.NumField(); i++ {
if !v.Field(i).IsZero() {
num++
}
}
return num
}

// validateTierForPolicy validates whether a referenced Tier exists.
func (v *antreaPolicyValidator) validateTierForPolicy(tier string) (string, bool) {
// "tier" must exist before referencing
Expand Down
36 changes: 36 additions & 0 deletions test/e2e/antreapolicy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2720,6 +2720,41 @@ func testToServices(t *testing.T) {
}
}

func testGroupStandAlonePeer(t *testing.T) {
builder1 := &ClusterNetworkPolicySpecBuilder{}
builder1 = builder1.SetName("group-not-alone-in-applied-to").
SetTier("application").
SetPriority(1.0).
SetAppliedToGroup([]ACNPAppliedToSpec{{Group: "cg-1", NSSelector: map[string]string{"ns": "x"}}})
builder1.AddIngress(v1.ProtocolTCP, nil, nil, nil, nil, nil, nil, nil, nil,
true, nil, crdv1alpha1.RuleActionPass, "cg-2", "")
_, err := k8sUtils.CreateOrUpdateACNP(builder1.Get())
if err == nil {
t.Error("failure -- group shouldn't be able to used with other field in `AppliedTo`")
failOnError(k8sUtils.DeleteACNP(builder1.Name), t)
failOnError(waitForResourceDelete("", builder1.Name, resourceACNP, timeout), t)
time.Sleep(networkPolicyDelay)
}

builder2 := &ClusterNetworkPolicySpecBuilder{}
builder2 = builder2.SetName("group-not-alone-in-rule").
SetTier("application").
SetPriority(1.0).
SetAppliedToGroup([]ACNPAppliedToSpec{{Group: "cg-1"}})
builder2.AddIngress(v1.ProtocolTCP, nil, nil, nil, nil, map[string]string{"pod": "a"}, nil, nil, nil,
true, nil, crdv1alpha1.RuleActionPass, "cg-2", "")
builder2.AddEgress(v1.ProtocolTCP, nil, nil, nil, nil, nil, nil, nil, nil,
true, nil, crdv1alpha1.RuleActionPass, "cg-2", "")
builder2.Spec.Egress[0].To[0].FQDN = "google.com"
_, err = k8sUtils.CreateOrUpdateACNP(builder2.Get())
if err == nil {
t.Error("failure -- group shouldn't be able to used with other fields in ingress.from or egress.to")
failOnError(k8sUtils.DeleteACNP(builder2.Name), t)
failOnError(waitForResourceDelete("", builder2.Name, resourceACNP, timeout), t)
time.Sleep(networkPolicyDelay)
}
}

// executeTests runs all the tests in testList and prints results
func executeTests(t *testing.T, testList []*TestCase) {
executeTestsWithData(t, testList, nil)
Expand Down Expand Up @@ -3067,6 +3102,7 @@ func TestAntreaPolicy(t *testing.T) {
t.Run("Case=ACNPFQDNPolicy", func(t *testing.T) { testFQDNPolicy(t) })
t.Run("Case=FQDNPolicyInCluster", func(t *testing.T) { testFQDNPolicyInClusterService(t) })
t.Run("Case=ACNPToServices", func(t *testing.T) { testToServices(t) })
t.Run("Case=ACNPGroupStandAlonePeer", func(t *testing.T) { testGroupStandAlonePeer(t) })
})
// print results for reachability tests
printResults()
Expand Down

0 comments on commit 5865840

Please sign in to comment.