github.com/cilium/cilium@v1.16.2/pkg/policy/correlation/correlation_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package correlation
     5  
     6  import (
     7  	"net"
     8  	"testing"
     9  
    10  	"github.com/google/go-cmp/cmp"
    11  	"github.com/stretchr/testify/require"
    12  	"google.golang.org/protobuf/testing/protocmp"
    13  
    14  	flowpb "github.com/cilium/cilium/api/v1/flow"
    15  	"github.com/cilium/cilium/pkg/hubble/parser/getters"
    16  	"github.com/cilium/cilium/pkg/hubble/testutils"
    17  	"github.com/cilium/cilium/pkg/identity"
    18  	"github.com/cilium/cilium/pkg/k8s/apis/cilium.io/utils"
    19  	"github.com/cilium/cilium/pkg/labels"
    20  	monitorAPI "github.com/cilium/cilium/pkg/monitor/api"
    21  	"github.com/cilium/cilium/pkg/policy"
    22  	"github.com/cilium/cilium/pkg/policy/trafficdirection"
    23  	"github.com/cilium/cilium/pkg/u8proto"
    24  )
    25  
    26  func TestCorrelatePolicy(t *testing.T) {
    27  	localIP := "1.2.3.4"
    28  	localIdentity := uint64(1234)
    29  	localID := uint64(12)
    30  	remoteIP := "5.6.7.8"
    31  	remoteIdentity := uint64(5678)
    32  	remoteID := uint64(56)
    33  	dstPort := uint32(443)
    34  
    35  	flow := &flowpb.Flow{
    36  		EventType: &flowpb.CiliumEventType{
    37  			Type: monitorAPI.MessageTypePolicyVerdict,
    38  		},
    39  		Verdict:          flowpb.Verdict_FORWARDED,
    40  		TrafficDirection: flowpb.TrafficDirection_EGRESS,
    41  		IP: &flowpb.IP{
    42  			Source:      localIP,
    43  			Destination: remoteIP,
    44  		},
    45  		L4: &flowpb.Layer4{
    46  			Protocol: &flowpb.Layer4_TCP{
    47  				TCP: &flowpb.TCP{
    48  					DestinationPort: dstPort,
    49  				},
    50  			},
    51  		},
    52  		Source: &flowpb.Endpoint{
    53  			ID:       uint32(localID),
    54  			Identity: uint32(localIdentity),
    55  		},
    56  		Destination: &flowpb.Endpoint{
    57  			ID:       uint32(remoteID),
    58  			Identity: uint32(remoteIdentity),
    59  		},
    60  		PolicyMatchType: monitorAPI.PolicyMatchL3L4,
    61  	}
    62  
    63  	policyLabel := utils.GetPolicyLabels("foo-namespace", "web-policy", "1234-5678", utils.ResourceTypeCiliumNetworkPolicy)
    64  	policyKey := policy.Key{
    65  		Identity:         uint32(remoteIdentity),
    66  		DestPort:         uint16(dstPort),
    67  		Nexthdr:          uint8(u8proto.TCP),
    68  		TrafficDirection: trafficdirection.Egress.Uint8(),
    69  	}
    70  	ep := &testutils.FakeEndpointInfo{
    71  		ID:           localID,
    72  		Identity:     identity.NumericIdentity(localIdentity),
    73  		IPv4:         net.ParseIP(localIP),
    74  		PodName:      "xwing",
    75  		PodNamespace: "default",
    76  		Labels:       []string{"a", "b", "c"},
    77  		PolicyMap: map[policy.Key]labels.LabelArrayList{
    78  			policyKey: {policyLabel},
    79  		},
    80  		PolicyRevision: 1,
    81  	}
    82  
    83  	endpointGetter := &testutils.FakeEndpointGetter{
    84  		OnGetEndpointInfoByID: func(id uint16) (endpoint getters.EndpointInfo, ok bool) {
    85  			if uint64(id) == ep.ID {
    86  				return ep, true
    87  			}
    88  			t.Fatalf("did not expect endpoint retrieval for non-local endpoint: %d", id)
    89  			return nil, false
    90  		},
    91  	}
    92  
    93  	CorrelatePolicy(endpointGetter, flow)
    94  
    95  	expected := []*flowpb.Policy{
    96  		{
    97  			Name:      "web-policy",
    98  			Namespace: "foo-namespace",
    99  			Labels: []string{
   100  				"k8s:io.cilium.k8s.policy.derived-from=CiliumNetworkPolicy",
   101  				"k8s:io.cilium.k8s.policy.name=web-policy",
   102  				"k8s:io.cilium.k8s.policy.namespace=foo-namespace",
   103  				"k8s:io.cilium.k8s.policy.uid=1234-5678",
   104  			},
   105  			Revision: 1,
   106  		},
   107  	}
   108  
   109  	require.Nil(t, flow.EgressDeniedBy)
   110  	require.Nil(t, flow.IngressDeniedBy)
   111  	require.Nil(t, flow.IngressAllowedBy)
   112  	if diff := cmp.Diff(expected, flow.EgressAllowedBy, protocmp.Transform()); diff != "" {
   113  		t.Fatalf("not equal (-want +got):\n%s", diff)
   114  	}
   115  
   116  	// check same flow at egress with deny
   117  	flow = &flowpb.Flow{
   118  		EventType: &flowpb.CiliumEventType{
   119  			Type: monitorAPI.MessageTypePolicyVerdict,
   120  		},
   121  		Verdict:          flowpb.Verdict_DROPPED,
   122  		DropReasonDesc:   flowpb.DropReason_POLICY_DENY,
   123  		TrafficDirection: flowpb.TrafficDirection_EGRESS,
   124  		IP: &flowpb.IP{
   125  			Source:      localIP,
   126  			Destination: remoteIP,
   127  		},
   128  		L4: &flowpb.Layer4{
   129  			Protocol: &flowpb.Layer4_TCP{
   130  				TCP: &flowpb.TCP{
   131  					DestinationPort: dstPort,
   132  				},
   133  			},
   134  		},
   135  		Source: &flowpb.Endpoint{
   136  			ID:       uint32(localID),
   137  			Identity: uint32(localIdentity),
   138  		},
   139  		Destination: &flowpb.Endpoint{
   140  			ID:       uint32(remoteID),
   141  			Identity: uint32(remoteIdentity),
   142  		},
   143  		PolicyMatchType: monitorAPI.PolicyMatchL3L4,
   144  	}
   145  	CorrelatePolicy(endpointGetter, flow)
   146  
   147  	require.Nil(t, flow.EgressAllowedBy)
   148  	require.Nil(t, flow.IngressAllowedBy)
   149  	require.Nil(t, flow.IngressDeniedBy)
   150  	if diff := cmp.Diff(expected, flow.EgressDeniedBy, protocmp.Transform()); diff != "" {
   151  		t.Fatalf("not equal (-want +got):\n%s", diff)
   152  	}
   153  
   154  	// check same flow at ingress
   155  	flow = &flowpb.Flow{
   156  		EventType: &flowpb.CiliumEventType{
   157  			Type: monitorAPI.MessageTypePolicyVerdict,
   158  		},
   159  		Verdict:          flowpb.Verdict_FORWARDED,
   160  		TrafficDirection: flowpb.TrafficDirection_INGRESS,
   161  		IP: &flowpb.IP{
   162  			Source:      localIP,
   163  			Destination: remoteIP,
   164  		},
   165  		L4: &flowpb.Layer4{
   166  			Protocol: &flowpb.Layer4_TCP{
   167  				TCP: &flowpb.TCP{
   168  					DestinationPort: dstPort,
   169  				},
   170  			},
   171  		},
   172  		Source: &flowpb.Endpoint{
   173  			ID:       uint32(localID),
   174  			Identity: uint32(localIdentity),
   175  		},
   176  		Destination: &flowpb.Endpoint{
   177  			ID:       uint32(remoteID),
   178  			Identity: uint32(remoteIdentity),
   179  		},
   180  		PolicyMatchType: monitorAPI.PolicyMatchL3Only,
   181  	}
   182  
   183  	policyKey = policy.Key{
   184  		Identity:         uint32(localIdentity),
   185  		DestPort:         0,
   186  		InvertedPortMask: 0xffff, // this is a wildcard
   187  		Nexthdr:          0,
   188  		TrafficDirection: trafficdirection.Ingress.Uint8(),
   189  	}
   190  	ep = &testutils.FakeEndpointInfo{
   191  		ID:           remoteID,
   192  		Identity:     identity.NumericIdentity(remoteIdentity),
   193  		IPv4:         net.ParseIP(remoteIP),
   194  		PodName:      "xwing",
   195  		PodNamespace: "default",
   196  		Labels:       []string{"a", "b", "c"},
   197  		PolicyMap: map[policy.Key]labels.LabelArrayList{
   198  			policyKey: {policyLabel},
   199  		},
   200  		PolicyRevision: 1,
   201  	}
   202  	endpointGetter = &testutils.FakeEndpointGetter{
   203  		OnGetEndpointInfoByID: func(id uint16) (endpoint getters.EndpointInfo, ok bool) {
   204  			if uint64(id) == ep.ID {
   205  				return ep, true
   206  			}
   207  			t.Fatalf("did not expect endpoint retrieval for non-remote endpoint: %d", id)
   208  			return nil, false
   209  		},
   210  	}
   211  	CorrelatePolicy(endpointGetter, flow)
   212  
   213  	require.Nil(t, flow.EgressDeniedBy)
   214  	require.Nil(t, flow.IngressDeniedBy)
   215  	require.Nil(t, flow.EgressAllowedBy)
   216  	if diff := cmp.Diff(expected, flow.IngressAllowedBy, protocmp.Transform()); diff != "" {
   217  		t.Fatalf("not equal (-want +got):\n%s", diff)
   218  	}
   219  
   220  	// check same flow at ingress with deny
   221  	flow = &flowpb.Flow{
   222  		EventType: &flowpb.CiliumEventType{
   223  			Type: monitorAPI.MessageTypePolicyVerdict,
   224  		},
   225  		Verdict:          flowpb.Verdict_DROPPED,
   226  		DropReasonDesc:   flowpb.DropReason_POLICY_DENY,
   227  		TrafficDirection: flowpb.TrafficDirection_INGRESS,
   228  		IP: &flowpb.IP{
   229  			Source:      localIP,
   230  			Destination: remoteIP,
   231  		},
   232  		L4: &flowpb.Layer4{
   233  			Protocol: &flowpb.Layer4_TCP{
   234  				TCP: &flowpb.TCP{
   235  					DestinationPort: dstPort,
   236  				},
   237  			},
   238  		},
   239  		Source: &flowpb.Endpoint{
   240  			ID:       uint32(localID),
   241  			Identity: uint32(localIdentity),
   242  		},
   243  		Destination: &flowpb.Endpoint{
   244  			ID:       uint32(remoteID),
   245  			Identity: uint32(remoteIdentity),
   246  		},
   247  		PolicyMatchType: monitorAPI.PolicyMatchL3Only,
   248  	}
   249  	CorrelatePolicy(endpointGetter, flow)
   250  
   251  	require.Nil(t, flow.EgressAllowedBy)
   252  	require.Nil(t, flow.IngressAllowedBy)
   253  	require.Nil(t, flow.EgressDeniedBy)
   254  	if diff := cmp.Diff(expected, flow.IngressDeniedBy, protocmp.Transform()); diff != "" {
   255  		t.Fatalf("not equal (-want +got):\n%s", diff)
   256  	}
   257  }