From f14e6b504a87a5d4d8868ced285a9426135c4b0e Mon Sep 17 00:00:00 2001 From: Kumar Atish Date: Fri, 3 Nov 2023 18:23:58 +0530 Subject: [PATCH] Add NetworkPolicy rule name in Traceflow observation Update Traceflow e2e tests to verify "NetworkPolicy" and "NetworkPolicyRule" in Traceflow observation. Signed-off-by: Kumar Atish --- build/charts/antrea/crds/traceflow.yaml | 2 + build/yamls/antrea-aks.yml | 2 + build/yamls/antrea-crds.yml | 2 + build/yamls/antrea-eks.yml | 2 + build/yamls/antrea-gke.yml | 2 + build/yamls/antrea-ipsec.yml | 2 + build/yamls/antrea.yml | 2 + pkg/agent/controller/traceflow/packetin.go | 9 + .../controller/traceflow/packetin_test.go | 265 ++++++++++++++++-- .../traceflow/traceflow_controller_test.go | 44 +-- pkg/apis/crd/v1beta1/types.go | 2 + pkg/apiserver/openapi/zz_generated.openapi.go | 7 + test/e2e/traceflow_test.go | 56 +++- 13 files changed, 343 insertions(+), 54 deletions(-) diff --git a/build/charts/antrea/crds/traceflow.yaml b/build/charts/antrea/crds/traceflow.yaml index 8f9ea0ec977..814e7f5de32 100644 --- a/build/charts/antrea/crds/traceflow.yaml +++ b/build/charts/antrea/crds/traceflow.yaml @@ -438,6 +438,8 @@ spec: type: string networkPolicy: type: string + networkPolicyRule: + type: string ttl: type: integer minimum: 0 diff --git a/build/yamls/antrea-aks.yml b/build/yamls/antrea-aks.yml index 0b08d80b60a..95c8dc7fe83 100644 --- a/build/yamls/antrea-aks.yml +++ b/build/yamls/antrea-aks.yml @@ -5048,6 +5048,8 @@ spec: type: string networkPolicy: type: string + networkPolicyRule: + type: string ttl: type: integer minimum: 0 diff --git a/build/yamls/antrea-crds.yml b/build/yamls/antrea-crds.yml index 7f24fc8ee19..4aa9e2d2f8a 100644 --- a/build/yamls/antrea-crds.yml +++ b/build/yamls/antrea-crds.yml @@ -5021,6 +5021,8 @@ spec: type: string networkPolicy: type: string + networkPolicyRule: + type: string ttl: type: integer minimum: 0 diff --git a/build/yamls/antrea-eks.yml b/build/yamls/antrea-eks.yml index 1ebcf9995d5..1b8362c2254 100644 --- a/build/yamls/antrea-eks.yml +++ b/build/yamls/antrea-eks.yml @@ -5048,6 +5048,8 @@ spec: type: string networkPolicy: type: string + networkPolicyRule: + type: string ttl: type: integer minimum: 0 diff --git a/build/yamls/antrea-gke.yml b/build/yamls/antrea-gke.yml index 572595eb632..176b5f844a2 100644 --- a/build/yamls/antrea-gke.yml +++ b/build/yamls/antrea-gke.yml @@ -5048,6 +5048,8 @@ spec: type: string networkPolicy: type: string + networkPolicyRule: + type: string ttl: type: integer minimum: 0 diff --git a/build/yamls/antrea-ipsec.yml b/build/yamls/antrea-ipsec.yml index a9cc6bd36d3..462aaec0ef5 100644 --- a/build/yamls/antrea-ipsec.yml +++ b/build/yamls/antrea-ipsec.yml @@ -5048,6 +5048,8 @@ spec: type: string networkPolicy: type: string + networkPolicyRule: + type: string ttl: type: integer minimum: 0 diff --git a/build/yamls/antrea.yml b/build/yamls/antrea.yml index 3227814289f..fab2a333a8c 100644 --- a/build/yamls/antrea.yml +++ b/build/yamls/antrea.yml @@ -5048,6 +5048,8 @@ spec: type: string networkPolicy: type: string + networkPolicyRule: + type: string ttl: type: integer minimum: 0 diff --git a/pkg/agent/controller/traceflow/packetin.go b/pkg/agent/controller/traceflow/packetin.go index 41a2040c1b1..8f331254d8b 100644 --- a/pkg/agent/controller/traceflow/packetin.go +++ b/pkg/agent/controller/traceflow/packetin.go @@ -207,6 +207,10 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1beta1.Traceflo npRef := c.networkPolicyQuerier.GetNetworkPolicyByRuleFlowID(egressInfo) if npRef != nil { ob.NetworkPolicy = npRef.ToString() + ruleRef := c.networkPolicyQuerier.GetRuleByFlowID(egressInfo) + if ruleRef != nil { + ob.NetworkPolicyRule = ruleRef.Name + } } obs = append(obs, *ob) } @@ -222,6 +226,10 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1beta1.Traceflo npRef := c.networkPolicyQuerier.GetNetworkPolicyByRuleFlowID(ingressInfo) if npRef != nil { ob.NetworkPolicy = npRef.ToString() + ruleRef := c.networkPolicyQuerier.GetRuleByFlowID(ingressInfo) + if ruleRef != nil { + ob.NetworkPolicyRule = ruleRef.Name + } } obs = append(obs, *ob) } @@ -237,6 +245,7 @@ func (c *Controller) parsePacketIn(pktIn *ofctrl.PacketIn) (*crdv1beta1.Traceflo if ruleRef := c.networkPolicyQuerier.GetRuleByFlowID(notAllowConjInfo); ruleRef != nil { if npRef := ruleRef.PolicyRef; npRef != nil { ob.NetworkPolicy = npRef.ToString() + ob.NetworkPolicyRule = ruleRef.Name } if ruleRef.Action != nil && *ruleRef.Action == crdv1beta1.RuleActionReject { ob.Action = crdv1beta1.ActionRejected diff --git a/pkg/agent/controller/traceflow/packetin_test.go b/pkg/agent/controller/traceflow/packetin_test.go index 6519cf76637..f548f2a3361 100644 --- a/pkg/agent/controller/traceflow/packetin_test.go +++ b/pkg/agent/controller/traceflow/packetin_test.go @@ -32,7 +32,10 @@ import ( "antrea.io/antrea/pkg/agent/config" "antrea.io/antrea/pkg/agent/openflow" + "antrea.io/antrea/pkg/agent/types" + "antrea.io/antrea/pkg/apis/controlplane/v1beta2" crdv1beta1 "antrea.io/antrea/pkg/apis/crd/v1beta1" + queriertest "antrea.io/antrea/pkg/querier/testing" ) var ( @@ -40,19 +43,6 @@ var ( egressIP = "192.168.100.100" ) -type fakeEgressQuerier struct { - egressName string - egressIP string -} - -func (f *fakeEgressQuerier) GetEgress(podNamespace, podName string) (string, string, error) { - return f.egressName, f.egressIP, nil -} - -func (f *fakeEgressQuerier) GetEgressIPByMark(mark uint32) (string, error) { - return f.egressIP, nil -} - func prepareMockTables() { openflow.InitMockTables( map[*openflow.Table]uint8{ @@ -211,7 +201,7 @@ func TestParseCapturedPacket(t *testing.T) { } } -func getTestPacketBytes() []byte { +func getTestPacketBytes(dstIPv4 string) []byte { ipPacket := &protocol.IPv4{ Version: 0x4, IHL: 5, @@ -249,12 +239,33 @@ func TestParsePacketIn(t *testing.T) { } matchTunDst := openflow15.NewTunnelIpv4DstField(net.ParseIP(egressIP), nil) - pktBytes := getTestPacketBytes() - - egressQuerier := &fakeEgressQuerier{ - egressName: egressName, - egressIP: egressIP, + conjData := make([]byte, 8) + binary.BigEndian.PutUint32(conjData[0:4], uint32(1)) + binary.BigEndian.PutUint32(conjData[4:8], uint32(2)) + matchTFEgressConjID := &openflow15.MatchField{ + Class: openflow15.OXM_CLASS_PACKET_REGS, + Field: uint8(openflow.TFEgressConjIDField.GetRegID() / 2), + Value: &openflow15.ByteArrayField{ + Data: conjData, + }, } + matchTFIngressConjID := &openflow15.MatchField{ + Class: openflow15.OXM_CLASS_PACKET_REGS, + Field: uint8(openflow.TFIngressConjIDField.GetRegID() / 2), + Value: &openflow15.ByteArrayField{ + Data: conjData, + }, + } + matchAPConjID := &openflow15.MatchField{ + Class: openflow15.OXM_CLASS_PACKET_REGS, + Field: uint8(openflow.APConjIDField.GetRegID() / 2), + Value: &openflow15.ByteArrayField{ + Data: conjData, + }, + } + + pktBytesPodToIP := getTestPacketBytes(dstIPv4) + pktBytesPodToPod := getTestPacketBytes(pod2IPv4) tests := []struct { name string @@ -262,6 +273,7 @@ func TestParsePacketIn(t *testing.T) { nodeConfig *config.NodeConfig tfState *traceflowState pktIn *ofctrl.PacketIn + expectedCalls func(*queriertest.MockAgentNetworkPolicyInfoQuerier, *queriertest.MockEgressQuerier) expectedTf *crdv1beta1.Traceflow expectedNodeResult *crdv1beta1.NodeResult }{ @@ -287,9 +299,13 @@ func TestParsePacketIn(t *testing.T) { Match: openflow15.Match{ Fields: []openflow15.MatchField{*matchOutPort, *matchPktMark}, }, - Data: util.NewBuffer(pktBytes), + Data: util.NewBuffer(pktBytesPodToIP), }, }, + expectedCalls: func(npQuerierq *queriertest.MockAgentNetworkPolicyInfoQuerier, egressQuerier *queriertest.MockEgressQuerier) { + egressQuerier.EXPECT().GetEgress(pod1.Namespace, pod1.Name).Return(egressName, egressIP, nil) + egressQuerier.EXPECT().GetEgressIPByMark(uint32(1)).Return(egressIP, nil) + }, expectedTf: &crdv1beta1.Traceflow{ ObjectMeta: metav1.ObjectMeta{ Name: "traceflow-pod-to-ipv4", @@ -350,9 +366,12 @@ func TestParsePacketIn(t *testing.T) { Match: openflow15.Match{ Fields: []openflow15.MatchField{*matchTunDst, *matchOutPort}, }, - Data: util.NewBuffer(pktBytes), + Data: util.NewBuffer(pktBytesPodToIP), }, }, + expectedCalls: func(npQuerierq *queriertest.MockAgentNetworkPolicyInfoQuerier, egressQuerier *queriertest.MockEgressQuerier) { + egressQuerier.EXPECT().GetEgress(pod1.Namespace, pod1.Name).Return(egressName, egressIP, nil) + }, expectedTf: &crdv1beta1.Traceflow{ ObjectMeta: metav1.ObjectMeta{ Name: "traceflow-pod-to-ipv4", @@ -413,9 +432,12 @@ func TestParsePacketIn(t *testing.T) { Match: openflow15.Match{ Fields: []openflow15.MatchField{*matchOutPort, *matchTunDst, *matchPktMark}, }, - Data: util.NewBuffer(pktBytes), + Data: util.NewBuffer(pktBytesPodToIP), }, }, + expectedCalls: func(npQuerierq *queriertest.MockAgentNetworkPolicyInfoQuerier, egressQuerier *queriertest.MockEgressQuerier) { + egressQuerier.EXPECT().GetEgressIPByMark(uint32(1)).Return(egressIP, nil) + }, expectedTf: &crdv1beta1.Traceflow{ ObjectMeta: metav1.ObjectMeta{ Name: "traceflow-pod-to-ipv4", @@ -453,16 +475,209 @@ func TestParsePacketIn(t *testing.T) { }, }, }, + { + name: "packet at source Node forwarded by acnp egress rule", + nodeConfig: &config.NodeConfig{}, + tfState: &traceflowState{ + name: "traceflow-pod-to-pod", + tag: 1, + isSender: true, + }, + pktIn: &ofctrl.PacketIn{ + PacketIn: &openflow15.PacketIn{ + TableId: openflow.EgressRuleTable.GetID(), + Match: openflow15.Match{ + Fields: []openflow15.MatchField{*matchTFEgressConjID}, + }, + Data: util.NewBuffer(pktBytesPodToPod), + }, + }, + expectedCalls: func(npQuerier *queriertest.MockAgentNetworkPolicyInfoQuerier, egressQuerier *queriertest.MockEgressQuerier) { + npQuerier.EXPECT().GetNetworkPolicyByRuleFlowID(uint32(2)).Return( + &v1beta2.NetworkPolicyReference{ + Type: v1beta2.AntreaClusterNetworkPolicy, + Name: "acnp-1", + }, + ) + npQuerier.EXPECT().GetRuleByFlowID(uint32(2)).Return( + &types.PolicyRule{ + Name: "egress-allow-rule", + }, + ) + }, + expectedTf: &crdv1beta1.Traceflow{ + ObjectMeta: metav1.ObjectMeta{ + Name: "traceflow-pod-to-pod", + }, + Spec: crdv1beta1.TraceflowSpec{ + Source: crdv1beta1.Source{ + Namespace: pod1.Namespace, + Pod: pod1.Name, + }, + Destination: crdv1beta1.Destination{ + Namespace: pod2.Namespace, + Pod: pod2.Name, + }, + }, + Status: crdv1beta1.TraceflowStatus{ + Phase: crdv1beta1.Running, + DataplaneTag: 1, + }, + }, + expectedNodeResult: &crdv1beta1.NodeResult{ + Observations: []crdv1beta1.Observation{ + { + Component: crdv1beta1.ComponentSpoofGuard, + Action: crdv1beta1.ActionForwarded, + }, + { + Component: crdv1beta1.ComponentNetworkPolicy, + ComponentInfo: openflow.EgressRuleTable.GetName(), + Action: crdv1beta1.ActionForwarded, + NetworkPolicy: string(v1beta2.AntreaClusterNetworkPolicy) + ":acnp-1", + NetworkPolicyRule: "egress-allow-rule", + }, + }, + }, + }, + { + name: "packet at destination Node forwarded by acnp ingress rule", + nodeConfig: &config.NodeConfig{}, + tfState: &traceflowState{ + name: "traceflow-pod-to-pod", + tag: 1, + }, + pktIn: &ofctrl.PacketIn{ + PacketIn: &openflow15.PacketIn{ + TableId: openflow.IngressRuleTable.GetID(), + Match: openflow15.Match{ + Fields: []openflow15.MatchField{*matchTFIngressConjID}, + }, + Data: util.NewBuffer(pktBytesPodToPod), + }, + }, + expectedCalls: func(npQuerier *queriertest.MockAgentNetworkPolicyInfoQuerier, egressQuerier *queriertest.MockEgressQuerier) { + npQuerier.EXPECT().GetNetworkPolicyByRuleFlowID(uint32(1)).Return( + &v1beta2.NetworkPolicyReference{ + Type: v1beta2.AntreaClusterNetworkPolicy, + Name: "acnp-2", + }, + ) + npQuerier.EXPECT().GetRuleByFlowID(uint32(1)).Return( + &types.PolicyRule{ + Name: "ingress-allow-rule", + }, + ) + }, + expectedTf: &crdv1beta1.Traceflow{ + ObjectMeta: metav1.ObjectMeta{ + Name: "traceflow-pod-to-pod", + }, + Spec: crdv1beta1.TraceflowSpec{ + Source: crdv1beta1.Source{ + Namespace: pod1.Namespace, + Pod: pod1.Name, + }, + Destination: crdv1beta1.Destination{ + Namespace: pod2.Namespace, + Pod: pod2.Name, + }, + }, + Status: crdv1beta1.TraceflowStatus{ + Phase: crdv1beta1.Running, + DataplaneTag: 1, + }, + }, + expectedNodeResult: &crdv1beta1.NodeResult{ + Observations: []crdv1beta1.Observation{ + { + Component: crdv1beta1.ComponentForwarding, + Action: crdv1beta1.ActionReceived, + }, + { + Component: crdv1beta1.ComponentNetworkPolicy, + ComponentInfo: openflow.IngressRuleTable.GetName(), + Action: crdv1beta1.ActionForwarded, + NetworkPolicy: string(v1beta2.AntreaClusterNetworkPolicy) + ":acnp-2", + NetworkPolicyRule: "ingress-allow-rule", + }, + }, + }, + }, + { + name: "packet at source Node dropped by acnp egress rule", + nodeConfig: &config.NodeConfig{}, + tfState: &traceflowState{ + name: "traceflow-pod-to-pod", + tag: 1, + isSender: true, + }, + pktIn: &ofctrl.PacketIn{ + PacketIn: &openflow15.PacketIn{ + TableId: openflow.EgressMetricTable.GetID(), + Match: openflow15.Match{ + Fields: []openflow15.MatchField{*matchAPConjID}, + }, + Data: util.NewBuffer(pktBytesPodToPod), + }, + }, + expectedCalls: func(npQuerier *queriertest.MockAgentNetworkPolicyInfoQuerier, egressQuerier *queriertest.MockEgressQuerier) { + npQuerier.EXPECT().GetRuleByFlowID(uint32(2)).Return( + &types.PolicyRule{ + Name: "egress-drop-rule", + PolicyRef: &v1beta2.NetworkPolicyReference{ + Type: v1beta2.AntreaClusterNetworkPolicy, + Name: "acnp-3", + }, + }, + ) + }, + expectedTf: &crdv1beta1.Traceflow{ + ObjectMeta: metav1.ObjectMeta{ + Name: "traceflow-pod-to-pod", + }, + Spec: crdv1beta1.TraceflowSpec{ + Source: crdv1beta1.Source{ + Namespace: pod1.Namespace, + Pod: pod1.Name, + }, + Destination: crdv1beta1.Destination{ + Namespace: pod2.Namespace, + Pod: pod2.Name, + }, + }, + Status: crdv1beta1.TraceflowStatus{ + Phase: crdv1beta1.Running, + DataplaneTag: 1, + }, + }, + expectedNodeResult: &crdv1beta1.NodeResult{ + Observations: []crdv1beta1.Observation{ + { + Component: crdv1beta1.ComponentSpoofGuard, + Action: crdv1beta1.ActionForwarded, + }, + { + Component: crdv1beta1.ComponentNetworkPolicy, + ComponentInfo: openflow.EgressMetricTable.GetName(), + Action: crdv1beta1.ActionDropped, + NetworkPolicy: string(v1beta2.AntreaClusterNetworkPolicy) + ":acnp-3", + NetworkPolicyRule: "egress-drop-rule", + }, + }, + }, + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - tfc := newFakeTraceflowController(t, []runtime.Object{tt.expectedTf}, tt.networkConfig, tt.nodeConfig, nil, egressQuerier) + tfc := newFakeTraceflowController(t, []runtime.Object{tt.expectedTf}, tt.networkConfig, tt.nodeConfig) stopCh := make(chan struct{}) defer close(stopCh) tfc.crdInformerFactory.Start(stopCh) tfc.crdInformerFactory.WaitForCacheSync(stopCh) tfc.runningTraceflows[tt.expectedTf.Status.DataplaneTag] = tt.tfState + tt.expectedCalls(tfc.networkPolicyQuerier, tfc.egressQuerier) tf, nodeResult, _, err := tfc.parsePacketIn(tt.pktIn) require.NoError(t, err) @@ -492,11 +707,11 @@ func TestParsePacketInLiveDuplicates(t *testing.T) { pktIn := &ofctrl.PacketIn{ PacketIn: &openflow15.PacketIn{ TableId: openflow.OutputTable.GetID(), - Data: util.NewBuffer(getTestPacketBytes()), + Data: util.NewBuffer(getTestPacketBytes(dstIPv4)), }, } - tfc := newFakeTraceflowController(t, nil, networkConfig, nodeConfig, nil, nil) + tfc := newFakeTraceflowController(t, nil, networkConfig, nodeConfig) tfc.runningTraceflows[tfState.tag] = tfState _, _, _, err := tfc.parsePacketIn(pktIn) diff --git a/pkg/agent/controller/traceflow/traceflow_controller_test.go b/pkg/agent/controller/traceflow/traceflow_controller_test.go index 9c9d3817630..3acd7e1adb2 100644 --- a/pkg/agent/controller/traceflow/traceflow_controller_test.go +++ b/pkg/agent/controller/traceflow/traceflow_controller_test.go @@ -41,7 +41,7 @@ import ( fakeversioned "antrea.io/antrea/pkg/client/clientset/versioned/fake" crdinformers "antrea.io/antrea/pkg/client/informers/externalversions" binding "antrea.io/antrea/pkg/ovs/openflow" - "antrea.io/antrea/pkg/querier" + queriertest "antrea.io/antrea/pkg/querier/testing" "antrea.io/antrea/pkg/util/k8s" ) @@ -83,20 +83,24 @@ var ( type fakeTraceflowController struct { *Controller - kubeClient kubernetes.Interface - mockController *gomock.Controller - mockOFClient *openflowtest.MockClient - crdClient *fakeversioned.Clientset - crdInformerFactory crdinformers.SharedInformerFactory + kubeClient kubernetes.Interface + mockController *gomock.Controller + mockOFClient *openflowtest.MockClient + crdClient *fakeversioned.Clientset + crdInformerFactory crdinformers.SharedInformerFactory + networkPolicyQuerier *queriertest.MockAgentNetworkPolicyInfoQuerier + egressQuerier *queriertest.MockEgressQuerier } -func newFakeTraceflowController(t *testing.T, initObjects []runtime.Object, networkConfig *config.NetworkConfig, nodeConfig *config.NodeConfig, npQuerier querier.AgentNetworkPolicyInfoQuerier, egressQuerier querier.EgressQuerier) *fakeTraceflowController { +func newFakeTraceflowController(t *testing.T, initObjects []runtime.Object, networkConfig *config.NetworkConfig, nodeConfig *config.NodeConfig) *fakeTraceflowController { controller := gomock.NewController(t) kubeClient := fake.NewSimpleClientset(&pod1, &pod2, &pod3) mockOFClient := openflowtest.NewMockClient(controller) crdClient := fakeversioned.NewSimpleClientset(initObjects...) crdInformerFactory := crdinformers.NewSharedInformerFactory(crdClient, 0) traceflowInformer := crdInformerFactory.Crd().V1beta1().Traceflows() + npQuerier := queriertest.NewMockAgentNetworkPolicyInfoQuerier(controller) + egressQuerier := queriertest.NewMockEgressQuerier(controller) ifaceStore := interfacestore.NewInterfaceStore() addPodInterface(ifaceStore, pod1.Namespace, pod1.Name, pod1IPv4, pod1MAC.String(), int32(ofPortPod1)) @@ -122,12 +126,14 @@ func newFakeTraceflowController(t *testing.T, initObjects []runtime.Object, netw } return &fakeTraceflowController{ - Controller: tfController, - kubeClient: kubeClient, - mockController: controller, - mockOFClient: mockOFClient, - crdClient: crdClient, - crdInformerFactory: crdInformerFactory, + Controller: tfController, + kubeClient: kubeClient, + mockController: controller, + mockOFClient: mockOFClient, + crdClient: crdClient, + crdInformerFactory: crdInformerFactory, + networkPolicyQuerier: npQuerier, + egressQuerier: egressQuerier, } } @@ -471,7 +477,7 @@ func TestPreparePacket(t *testing.T) { for _, tt := range tcs { t.Run(tt.name, func(t *testing.T) { - tfc := newFakeTraceflowController(t, []runtime.Object{tt.tf}, nil, nil, nil, nil) + tfc := newFakeTraceflowController(t, []runtime.Object{tt.tf}, nil, nil) podInterfaces := tfc.interfaceStore.GetContainerInterfacesByPod(pod1.Name, pod1.Namespace) if tt.intf != nil { podInterfaces[0] = tt.intf @@ -515,7 +521,7 @@ func TestErrTraceflowCRD(t *testing.T) { expectedTf.Status.Phase = crdv1beta1.Failed expectedTf.Status.Reason = reason - tfc := newFakeTraceflowController(t, []runtime.Object{tf}, nil, nil, nil, nil) + tfc := newFakeTraceflowController(t, []runtime.Object{tf}, nil, nil) gotTf, err := tfc.errorTraceflowCRD(tf, reason) require.NoError(t, err) @@ -640,7 +646,7 @@ func TestStartTraceflow(t *testing.T) { for _, tt := range tcs { t.Run(tt.name, func(t *testing.T) { - tfc := newFakeTraceflowController(t, []runtime.Object{tt.tf}, nil, tt.nodeConfig, nil, nil) + tfc := newFakeTraceflowController(t, []runtime.Object{tt.tf}, nil, tt.nodeConfig) if tt.expectedCalls != nil { tt.expectedCalls(tfc.mockOFClient) } @@ -728,7 +734,7 @@ func TestSyncTraceflow(t *testing.T) { for _, tt := range tcs { t.Run(tt.name, func(t *testing.T) { - tfc := newFakeTraceflowController(t, []runtime.Object{tt.tf}, nil, nil, nil, nil) + tfc := newFakeTraceflowController(t, []runtime.Object{tt.tf}, nil, nil) stopCh := make(chan struct{}) defer close(stopCh) tfc.crdInformerFactory.Start(stopCh) @@ -783,7 +789,7 @@ func TestProcessTraceflowItem(t *testing.T) { expected: true, } - tfc := newFakeTraceflowController(t, []runtime.Object{tc.tf}, nil, nil, nil, nil) + tfc := newFakeTraceflowController(t, []runtime.Object{tc.tf}, nil, nil) stopCh := make(chan struct{}) defer close(stopCh) tfc.crdInformerFactory.Start(stopCh) @@ -829,7 +835,7 @@ func TestValidateTraceflow(t *testing.T) { for _, tt := range tcs { t.Run(tt.name, func(t *testing.T) { - tfc := newFakeTraceflowController(t, []runtime.Object{tt.tf}, nil, nil, nil, nil) + tfc := newFakeTraceflowController(t, []runtime.Object{tt.tf}, nil, nil) tfc.enableAntreaProxy = tt.antreaProxyEnabled err := tfc.validateTraceflow(tt.tf) assert.ErrorContains(t, err, tt.expectedErr) diff --git a/pkg/apis/crd/v1beta1/types.go b/pkg/apis/crd/v1beta1/types.go index 08ce6248a22..77aa05e6d4b 100644 --- a/pkg/apis/crd/v1beta1/types.go +++ b/pkg/apis/crd/v1beta1/types.go @@ -1135,6 +1135,8 @@ type Observation struct { DstMAC string `json:"dstMAC,omitempty" yaml:"dstMAC,omitempty"` // NetworkPolicy is the combination of Namespace and NetworkPolicyName. NetworkPolicy string `json:"networkPolicy,omitempty" yaml:"networkPolicy,omitempty"` + // NetworkPolicyRule is the name of an ingress or an egress rule in NetworkPolicy. + NetworkPolicyRule string `json:"networkPolicyRule,omitempty" yaml:"networkPolicyRule,omitempty"` // Egress is the name of the Egress. Egress string `json:"egress,omitempty" yaml:"egress,omitempty"` // TTL is the observation TTL. diff --git a/pkg/apiserver/openapi/zz_generated.openapi.go b/pkg/apiserver/openapi/zz_generated.openapi.go index ea9e911f76e..c7f00b2b8a8 100644 --- a/pkg/apiserver/openapi/zz_generated.openapi.go +++ b/pkg/apiserver/openapi/zz_generated.openapi.go @@ -4936,6 +4936,13 @@ func schema_pkg_apis_crd_v1beta1_Observation(ref common.ReferenceCallback) commo Format: "", }, }, + "networkPolicyRule": { + SchemaProps: spec.SchemaProps{ + Description: "NetworkPolicyRule is the name of an ingress or an egress rule in NetworkPolicy.", + Type: []string{"string"}, + Format: "", + }, + }, "egress": { SchemaProps: spec.SchemaProps{ Description: "Egress is the name of the Egress.", diff --git a/test/e2e/traceflow_test.go b/test/e2e/traceflow_test.go index 028fb648fa5..6f10f1c4feb 100644 --- a/test/e2e/traceflow_test.go +++ b/test/e2e/traceflow_test.go @@ -188,9 +188,11 @@ func testTraceflowIntraNodeANNP(t *testing.T, data *TestData) { Action: v1beta1.ActionForwarded, }, { - Component: v1beta1.ComponentNetworkPolicy, - ComponentInfo: "IngressMetric", - Action: v1beta1.ActionDropped, + Component: v1beta1.ComponentNetworkPolicy, + ComponentInfo: "IngressMetric", + Action: v1beta1.ActionDropped, + NetworkPolicy: fmt.Sprintf("AntreaNetworkPolicy:%s/test-annp-deny-ingress", data.testNamespace), + NetworkPolicyRule: "ingress-drop", }, }, }, @@ -236,9 +238,11 @@ func testTraceflowIntraNodeANNP(t *testing.T, data *TestData) { Action: v1beta1.ActionForwarded, }, { - Component: v1beta1.ComponentNetworkPolicy, - ComponentInfo: "IngressMetric", - Action: v1beta1.ActionRejected, + Component: v1beta1.ComponentNetworkPolicy, + ComponentInfo: "IngressMetric", + Action: v1beta1.ActionRejected, + NetworkPolicy: fmt.Sprintf("AntreaNetworkPolicy:%s/test-annp-reject-ingress", data.testNamespace), + NetworkPolicyRule: "ingress-reject", }, }, }, @@ -284,9 +288,11 @@ func testTraceflowIntraNodeANNP(t *testing.T, data *TestData) { Action: v1beta1.ActionForwarded, }, { - Component: v1beta1.ComponentNetworkPolicy, - ComponentInfo: "IngressMetric", - Action: v1beta1.ActionDropped, + Component: v1beta1.ComponentNetworkPolicy, + ComponentInfo: "IngressMetric", + Action: v1beta1.ActionDropped, + NetworkPolicy: fmt.Sprintf("AntreaNetworkPolicy:%s/test-annp-deny-ingress", data.testNamespace), + NetworkPolicyRule: "ingress-drop", }, }, }, @@ -421,6 +427,7 @@ func testTraceflowIntraNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentNetworkPolicy, @@ -473,6 +480,7 @@ func testTraceflowIntraNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -524,6 +532,7 @@ func testTraceflowIntraNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -569,6 +578,7 @@ func testTraceflowIntraNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -632,6 +642,7 @@ func testTraceflowIntraNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -746,11 +757,13 @@ func testTraceflowIntraNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "IngressDefaultRule", Action: v1beta1.ActionDropped, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, }, }, @@ -798,6 +811,7 @@ func testTraceflowIntraNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -849,6 +863,7 @@ func testTraceflowIntraNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -894,6 +909,7 @@ func testTraceflowIntraNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -967,6 +983,7 @@ func testTraceflowIntraNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -1015,6 +1032,7 @@ func testTraceflowIntraNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -1063,6 +1081,7 @@ func testTraceflowIntraNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -1227,6 +1246,7 @@ func testTraceflowInterNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -1292,6 +1312,7 @@ func testTraceflowInterNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -1352,6 +1373,7 @@ func testTraceflowInterNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -1428,6 +1450,7 @@ func testTraceflowInterNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -1505,6 +1528,7 @@ func testTraceflowInterNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -1548,6 +1572,7 @@ func testTraceflowInterNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -1615,6 +1640,7 @@ func testTraceflowInterNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -1683,6 +1709,7 @@ func testTraceflowInterNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -1742,6 +1769,7 @@ func testTraceflowInterNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -1815,6 +1843,7 @@ func testTraceflowInterNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -1889,6 +1918,7 @@ func testTraceflowInterNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -1937,6 +1967,7 @@ func testTraceflowInterNode(t *testing.T, data *TestData) { Component: v1beta1.ComponentNetworkPolicy, ComponentInfo: "EgressRule", Action: v1beta1.ActionForwarded, + NetworkPolicy: fmt.Sprintf("K8sNetworkPolicy:%s/test-networkpolicy-allow-all-egress", data.testNamespace), }, { Component: v1beta1.ComponentForwarding, @@ -2314,7 +2345,9 @@ func compareObservations(expected v1beta1.NodeResult, actual v1beta1.NodeResult) exObs[i].TranslatedDstIP != acObs[i].TranslatedDstIP || exObs[i].EgressIP != acObs[i].EgressIP || exObs[i].Egress != acObs[i].Egress || - exObs[i].Action != acObs[i].Action { + exObs[i].Action != acObs[i].Action || + exObs[i].NetworkPolicy != acObs[i].NetworkPolicy || + exObs[i].NetworkPolicyRule != acObs[i].NetworkPolicyRule { return fmt.Errorf("Observations should be %v, but got %v", exObs, acObs) } } @@ -2324,8 +2357,10 @@ func compareObservations(expected v1beta1.NodeResult, actual v1beta1.NodeResult) // createANNPDenyIngress creates an Antrea NetworkPolicy that denies ingress traffic for pods of specific label. func (data *TestData) createANNPDenyIngress(key string, value string, name string, isReject bool) (*v1beta1.NetworkPolicy, error) { dropACT := v1beta1.RuleActionDrop + ingressRuleName := "ingress-drop" if isReject { dropACT = v1beta1.RuleActionReject + ingressRuleName = "ingress-reject" } annp := v1beta1.NetworkPolicy{ ObjectMeta: metav1.ObjectMeta{ @@ -2352,6 +2387,7 @@ func (data *TestData) createANNPDenyIngress(key string, value string, name strin Action: &dropACT, Ports: []v1beta1.NetworkPolicyPort{}, From: []v1beta1.NetworkPolicyPeer{}, + Name: ingressRuleName, }, }, Egress: []v1beta1.Rule{},