From 933e5cba69b5643df1db0a959427119ef780bf99 Mon Sep 17 00:00:00 2001 From: Qiyue Yao <39061776+qiyueyao@users.noreply.github.com> Date: Wed, 3 Apr 2024 14:13:02 -0700 Subject: [PATCH] Add Action to NetworkPolicy Evaluation response (#6112) As necessary for networkpolicyevaluation consumption, this PR adds the Action field to the above antctl command response. Signed-off-by: Qiyue Yao --- pkg/antctl/output/output.go | 3 +- .../transform/networkpolicy/response.go | 15 +++- .../transform/networkpolicy/response_test.go | 69 ++++++++++++++++--- pkg/apiserver/apis/types.go | 2 +- .../networkpolicy/endpoint_querier.go | 8 +-- .../networkpolicy/endpoint_querier_test.go | 7 +- pkg/controller/types/networkpolicy.go | 2 +- 7 files changed, 82 insertions(+), 24 deletions(-) diff --git a/pkg/antctl/output/output.go b/pkg/antctl/output/output.go index 312bad3f9a8..8919219fd60 100644 --- a/pkg/antctl/output/output.go +++ b/pkg/antctl/output/output.go @@ -21,7 +21,6 @@ import ( "io" "reflect" "sort" - "strconv" "strings" "text/tabwriter" @@ -322,7 +321,7 @@ func TableOutputForQueryEndpoint(obj interface{}, writer io.Writer) error { toStringRep := func(effectiveRules []apis.Rule) [][]string { ruleStrings := make([][]string, 0) for _, rule := range effectiveRules { - ruleStrings = append(ruleStrings, []string{rule.PolicyRef.Name, rule.PolicyRef.Namespace, strconv.Itoa(rule.RuleIndex), string(rule.PolicyRef.UID)}) + ruleStrings = append(ruleStrings, []string{rule.PolicyRef.Name, rule.PolicyRef.Namespace, fmt.Sprint(rule.RuleIndex), string(rule.PolicyRef.UID)}) } return ruleStrings } diff --git a/pkg/antctl/transform/networkpolicy/response.go b/pkg/antctl/transform/networkpolicy/response.go index 53991b5edfb..74a762a54c2 100644 --- a/pkg/antctl/transform/networkpolicy/response.go +++ b/pkg/antctl/transform/networkpolicy/response.go @@ -17,6 +17,7 @@ package networkpolicy import ( "encoding/json" "io" + "math" "reflect" "sort" "strconv" @@ -181,20 +182,30 @@ func EvaluationTransform(reader io.Reader, _ bool, _ map[string]string) (interfa var _ common.TableOutput = new(EvaluationResponse) func (r EvaluationResponse) GetTableHeader() []string { - return []string{"NAME", "NAMESPACE", "POLICY-TYPE", "RULE-INDEX", "DIRECTION"} + return []string{"NAME", "NAMESPACE", "POLICY-TYPE", "RULE-INDEX", "DIRECTION", "ACTION"} } func (r EvaluationResponse) GetTableRow(_ int) []string { if r.NetworkPolicyEvaluation != nil && r.Response != nil { + // Handle K8s NPs empty action field. "Allow" corresponds to a K8s NP + // allow action, and "Isolate" corresponds to a drop action because of the + // default isolation model. Otherwise, display the action field content. + action := "Allow" + if r.Response.Rule.Action != nil { + action = string(*r.Response.Rule.Action) + } else if r.Response.RuleIndex == math.MaxInt32 { + action = "Isolate" + } return []string{ r.Response.NetworkPolicy.Name, r.Response.NetworkPolicy.Namespace, string(r.Response.NetworkPolicy.Type), strconv.Itoa(int(r.Response.RuleIndex)), string(r.Response.Rule.Direction), + action, } } - return make([]string, 5) + return make([]string, len(r.GetTableHeader())) } func (r EvaluationResponse) SortRows() bool { diff --git a/pkg/antctl/transform/networkpolicy/response_test.go b/pkg/antctl/transform/networkpolicy/response_test.go index 3720f366c55..d2f4e4c348d 100644 --- a/pkg/antctl/transform/networkpolicy/response_test.go +++ b/pkg/antctl/transform/networkpolicy/response_test.go @@ -15,6 +15,8 @@ package networkpolicy import ( + "fmt" + "math" "testing" "github.com/stretchr/testify/assert" @@ -23,6 +25,7 @@ import ( "k8s.io/utils/ptr" cpv1beta "antrea.io/antrea/pkg/apis/controlplane/v1beta2" + crdv1beta1 "antrea.io/antrea/pkg/apis/crd/v1beta1" ) func TestListTransform(t *testing.T) { @@ -176,17 +179,61 @@ func TestListTransform(t *testing.T) { func TestEvaluationResponseTransform(t *testing.T) { test := EvaluationResponse{&cpv1beta.NetworkPolicyEvaluation{}} - assert.Equal(t, []string{"NAME", "NAMESPACE", "POLICY-TYPE", "RULE-INDEX", "DIRECTION"}, test.GetTableHeader()) + assert.Equal(t, []string{"NAME", "NAMESPACE", "POLICY-TYPE", "RULE-INDEX", "DIRECTION", "ACTION"}, test.GetTableHeader()) assert.False(t, test.SortRows()) - assert.Equal(t, []string{"", "", "", "", ""}, test.GetTableRow(32)) - test.Response = &cpv1beta.NetworkPolicyEvaluationResponse{ - NetworkPolicy: cpv1beta.NetworkPolicyReference{ - Type: cpv1beta.K8sNetworkPolicy, - Namespace: "ns", - Name: "testName", - }, - RuleIndex: 10, - Rule: cpv1beta.RuleRef{Direction: cpv1beta.DirectionIn}, + assert.Equal(t, []string{"", "", "", "", "", ""}, test.GetTableRow(32)) + testDropAction := crdv1beta1.RuleActionDrop + + tests := []struct { + name string + testResponse *cpv1beta.NetworkPolicyEvaluationResponse + expectedOutput []string + }{ + { + name: "k8s rule", + testResponse: &cpv1beta.NetworkPolicyEvaluationResponse{ + NetworkPolicy: cpv1beta.NetworkPolicyReference{ + Type: cpv1beta.K8sNetworkPolicy, + Namespace: "ns", + Name: "testK8s", + }, + RuleIndex: 10, + Rule: cpv1beta.RuleRef{Direction: cpv1beta.DirectionIn}, + }, + expectedOutput: []string{"testK8s", "ns", "K8sNetworkPolicy", "10", "In", "Allow"}, + }, + { + name: "anp rule", + testResponse: &cpv1beta.NetworkPolicyEvaluationResponse{ + NetworkPolicy: cpv1beta.NetworkPolicyReference{ + Type: cpv1beta.AntreaNetworkPolicy, + Namespace: "ns", + Name: "testANP", + }, + RuleIndex: 10, + Rule: cpv1beta.RuleRef{Direction: cpv1beta.DirectionIn, Action: &testDropAction}, + }, + expectedOutput: []string{"testANP", "ns", "AntreaNetworkPolicy", "10", "In", "Drop"}, + }, + { + name: "k8s default isolation", + testResponse: &cpv1beta.NetworkPolicyEvaluationResponse{ + NetworkPolicy: cpv1beta.NetworkPolicyReference{ + Type: cpv1beta.K8sNetworkPolicy, + Namespace: "ns", + Name: "testK8s", + }, + RuleIndex: math.MaxInt32, + Rule: cpv1beta.RuleRef{Direction: cpv1beta.DirectionIn}, + }, + expectedOutput: []string{"testK8s", "ns", "K8sNetworkPolicy", fmt.Sprint(math.MaxInt32), "In", "Isolate"}, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + test.Response = tt.testResponse + assert.Equal(t, tt.expectedOutput, test.GetTableRow(32)) + }) } - assert.Equal(t, []string{"testName", "ns", "K8sNetworkPolicy", "10", "In"}, test.GetTableRow(32)) } diff --git a/pkg/apiserver/apis/types.go b/pkg/apiserver/apis/types.go index 87947000bbb..da671cded1c 100644 --- a/pkg/apiserver/apis/types.go +++ b/pkg/apiserver/apis/types.go @@ -24,7 +24,7 @@ type EndpointQueryResponse struct { type Rule struct { PolicyRef v1beta2.NetworkPolicyReference `json:"policyref,omitempty"` Direction v1beta2.Direction `json:"direction,omitempty"` - RuleIndex int `json:"ruleindex,omitempty"` + RuleIndex int32 `json:"ruleindex,omitempty"` } type Endpoint struct { diff --git a/pkg/controller/networkpolicy/endpoint_querier.go b/pkg/controller/networkpolicy/endpoint_querier.go index 031a31cb554..561d8b696d4 100644 --- a/pkg/controller/networkpolicy/endpoint_querier.go +++ b/pkg/controller/networkpolicy/endpoint_querier.go @@ -146,7 +146,7 @@ func (eq *EndpointQuerierImpl) QueryNetworkPolicyRules(namespace, podName string return nil, err } for _, policy := range policies { - egressIndex, ingressIndex := 0, 0 + egressIndex, ingressIndex := int32(0), int32(0) for _, rule := range policy.(*antreatypes.NetworkPolicy).Rules { for _, addressGroupTrial := range rule.To.AddressGroups { if addressGroupTrial == string(addressGroup.(*antreatypes.AddressGroup).UID) { @@ -191,10 +191,10 @@ func processEndpointAppliedRules(appliedPolicies []*antreatypes.NetworkPolicy, i // check if the Kubernetes NetworkPolicy creates ingress or egress isolationRules for _, rule := range internalPolicy.Rules { if rule.Direction == controlplane.DirectionIn && !isSourceEndpoint { - isolationRules = append(isolationRules, &antreatypes.RuleInfo{Policy: internalPolicy, Index: math.MaxInt, + isolationRules = append(isolationRules, &antreatypes.RuleInfo{Policy: internalPolicy, Index: math.MaxInt32, Rule: &controlplane.NetworkPolicyRule{Direction: rule.Direction, Name: rule.Name, Action: rule.Action}}) } else if rule.Direction == controlplane.DirectionOut && isSourceEndpoint { - isolationRules = append(isolationRules, &antreatypes.RuleInfo{Policy: internalPolicy, Index: math.MaxInt, + isolationRules = append(isolationRules, &antreatypes.RuleInfo{Policy: internalPolicy, Index: math.MaxInt32, Rule: &controlplane.NetworkPolicyRule{Direction: rule.Direction, Name: rule.Name, Action: rule.Action}}) } } @@ -313,7 +313,7 @@ func (eq *policyRuleQuerier) QueryNetworkPolicyEvaluation(entities *controlplane } return &controlplane.NetworkPolicyEvaluationResponse{ NetworkPolicy: *endpointAnalysisRule.Policy.SourceRef, - RuleIndex: int32(endpointAnalysisRule.Index), + RuleIndex: endpointAnalysisRule.Index, Rule: controlplane.RuleRef{ Direction: endpointAnalysisRule.Rule.Direction, Name: endpointAnalysisRule.Rule.Name, diff --git a/pkg/controller/networkpolicy/endpoint_querier_test.go b/pkg/controller/networkpolicy/endpoint_querier_test.go index 9edbc317550..fc296b3ffe9 100644 --- a/pkg/controller/networkpolicy/endpoint_querier_test.go +++ b/pkg/controller/networkpolicy/endpoint_querier_test.go @@ -16,6 +16,7 @@ package networkpolicy import ( "fmt" + "math" "testing" "time" @@ -395,7 +396,7 @@ func TestQueryNetworkPolicyEvaluation(t *testing.T) { for i := 0; i < len(policy.Rules); i++ { ruleInfoMatches[i] = &antreatypes.RuleInfo{ Policy: policy, - Index: i, + Index: int32(i), Rule: &controlplane.NetworkPolicyRule{Direction: policy.Rules[i].Direction, Name: policy.Rules[i].Name, Action: policy.Rules[i].Action}, } } @@ -529,7 +530,7 @@ func TestQueryNetworkPolicyEvaluation(t *testing.T) { }, expectedResult: &controlplane.NetworkPolicyEvaluationResponse{ NetworkPolicy: controlplane.NetworkPolicyReference{Type: controlplane.K8sNetworkPolicy, Namespace: namespace, Name: "Policy111", UID: uid1}, - RuleIndex: -1, + RuleIndex: math.MaxInt32, Rule: controlplane.RuleRef{Direction: controlplane.DirectionOut, Name: "Policy111Rule0"}, }, }, @@ -542,7 +543,7 @@ func TestQueryNetworkPolicyEvaluation(t *testing.T) { }, expectedResult: &controlplane.NetworkPolicyEvaluationResponse{ NetworkPolicy: controlplane.NetworkPolicyReference{Type: controlplane.K8sNetworkPolicy, Namespace: namespace, Name: "Policy222", UID: uid2}, - RuleIndex: -1, + RuleIndex: math.MaxInt32, Rule: controlplane.RuleRef{Direction: controlplane.DirectionIn, Name: "Policy222Rule0"}, }, }, diff --git a/pkg/controller/types/networkpolicy.go b/pkg/controller/types/networkpolicy.go index 86ca232ae2a..1f99d246f8a 100644 --- a/pkg/controller/types/networkpolicy.go +++ b/pkg/controller/types/networkpolicy.go @@ -139,7 +139,7 @@ func (p *NetworkPolicy) GetAppliedToGroups() sets.Set[string] { // corresponding ingress/egress rules, and the original rule info. type RuleInfo struct { Policy *NetworkPolicy - Index int + Index int32 Rule *controlplane.NetworkPolicyRule }