github.com/cilium/cilium@v1.16.2/pkg/hubble/filters/ip_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Hubble
     3  
     4  package filters
     5  
     6  import (
     7  	"context"
     8  	"testing"
     9  
    10  	flowpb "github.com/cilium/cilium/api/v1/flow"
    11  	v1 "github.com/cilium/cilium/pkg/hubble/api/v1"
    12  )
    13  
    14  func TestIPFilter(t *testing.T) {
    15  	type args struct {
    16  		f  []*flowpb.FlowFilter
    17  		ev []*v1.Event
    18  	}
    19  	tests := []struct {
    20  		name    string
    21  		args    args
    22  		wantErr bool
    23  		want    []bool
    24  	}{
    25  		{
    26  			name: "source ip",
    27  			args: args{
    28  				f: []*flowpb.FlowFilter{
    29  					{SourceIp: []string{"1.1.1.1", "f00d::a10:0:0:9195"}},
    30  				},
    31  				ev: []*v1.Event{
    32  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "1.1.1.1", Destination: "10.0.0.2"}}},
    33  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "10.0.0.2", Destination: "1.1.1.1"}}},
    34  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "f00d::a10:0:0:9195", Destination: "ff02::1:ff00:b3e5"}}},
    35  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "ff02::1:ff00:b3e5", Destination: "f00d::a10:0:0:9195"}}},
    36  				},
    37  			},
    38  			want: []bool{
    39  				true,
    40  				false,
    41  				true,
    42  				false,
    43  			},
    44  		},
    45  		{
    46  			name: "destination ip",
    47  			args: args{
    48  				f: []*flowpb.FlowFilter{
    49  					{DestinationIp: []string{"1.1.1.1", "f00d::a10:0:0:9195"}},
    50  				},
    51  				ev: []*v1.Event{
    52  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "1.1.1.1", Destination: "10.0.0.2"}}},
    53  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "10.0.0.2", Destination: "1.1.1.1"}}},
    54  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "f00d::a10:0:0:9195", Destination: "ff02::1:ff00:b3e5"}}},
    55  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "ff02::1:ff00:b3e5", Destination: "f00d::a10:0:0:9195"}}},
    56  				},
    57  			},
    58  			want: []bool{
    59  				false,
    60  				true,
    61  				false,
    62  				true,
    63  			},
    64  		},
    65  		{
    66  			name: "snat ip",
    67  			args: args{
    68  				f: []*flowpb.FlowFilter{
    69  					{SourceIpXlated: []string{"2.2.2.2", "9bf2:8d06:6d34:da3b::33c5"}},
    70  				},
    71  				ev: []*v1.Event{
    72  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "1.1.1.1", Destination: "10.0.0.2"}}},
    73  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "2.2.2.2", Destination: "10.0.0.2"}}},
    74  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "1.1.1.1", SourceXlated: "2.2.2.3", Destination: "10.0.0.2"}}},
    75  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "1.1.1.1", SourceXlated: "2.2.2.2", Destination: "10.0.0.2"}}},
    76  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "f00d::a10:0:0:9195", Destination: "ff02::1:ff00:b3e5"}}},
    77  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "f00d::a10:0:0:9195", Destination: "9bf2:8d06:6d34:da3b::33c5"}}},
    78  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "f00d::a10:0:0:9195", SourceXlated: "9bf2:8d06:6d34:da3b::33c5", Destination: "ff02::1:ff00:b3e5"}}},
    79  				},
    80  			},
    81  			want: []bool{
    82  				false,
    83  				false,
    84  				false,
    85  				true,
    86  				false,
    87  				false,
    88  				true,
    89  			},
    90  		},
    91  		{
    92  			name: "source and destination ip",
    93  			args: args{
    94  				f: []*flowpb.FlowFilter{
    95  					{
    96  						SourceIp:      []string{"1.1.1.1", "f00d::a10:0:0:9195"},
    97  						DestinationIp: []string{"10.0.0.2", "ff02::1:ff00:b3e5"},
    98  					},
    99  				},
   100  				ev: []*v1.Event{
   101  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "1.1.1.1", Destination: "10.0.0.2"}}},
   102  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "10.0.0.2", Destination: "1.1.1.1"}}},
   103  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "f00d::a10:0:0:9195", Destination: "ff02::1:ff00:b3e5"}}},
   104  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "ff02::1:ff00:b3e5", Destination: "f00d::a10:0:0:9195"}}},
   105  				},
   106  			},
   107  			want: []bool{
   108  				true,
   109  				false,
   110  				true,
   111  				false,
   112  			},
   113  		},
   114  		{
   115  			name: "source and snat and destination ip",
   116  			args: args{
   117  				f: []*flowpb.FlowFilter{
   118  					{
   119  						SourceIp:       []string{"1.1.1.1", "f00d::a10:0:0:9195"},
   120  						SourceIpXlated: []string{"2.2.2.2", "9bf2:8d06:6d34:da3b::33c5"},
   121  						DestinationIp:  []string{"10.0.0.2", "ff02::1:ff00:b3e5"},
   122  					},
   123  				},
   124  				ev: []*v1.Event{
   125  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "1.1.1.1", SourceXlated: "2.2.2.2", Destination: "10.0.0.2"}}},
   126  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "1.1.1.1", Destination: "10.0.0.2"}}},
   127  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "f00d::a10:0:0:9195", SourceXlated: "9bf2:8d06:6d34:da3b::33c5", Destination: "ff02::1:ff00:b3e5"}}},
   128  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "f00d::a10:0:0:9195", SourceXlated: "ff02::1:ff00:b3e5", Destination: "9bf2:8d06:6d34:da3b::33c5"}}},
   129  				},
   130  			},
   131  			want: []bool{
   132  				true,
   133  				false,
   134  				true,
   135  				false,
   136  			},
   137  		},
   138  		{
   139  			name: "source or destination ip",
   140  			args: args{
   141  				f: []*flowpb.FlowFilter{
   142  					{SourceIp: []string{"1.1.1.1"}},
   143  					{DestinationIp: []string{"10.0.0.2"}},
   144  				},
   145  				ev: []*v1.Event{
   146  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "1.1.1.1", Destination: "10.0.0.2"}}},
   147  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "10.0.0.2", Destination: "1.1.1.1"}}},
   148  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "1.1.1.1", Destination: "1.1.1.1"}}},
   149  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "10.0.0.2", Destination: "10.0.0.2"}}},
   150  				},
   151  			},
   152  			want: []bool{
   153  				true,
   154  				false,
   155  				true,
   156  				true,
   157  			},
   158  		},
   159  		{
   160  			name: "invalid data",
   161  			args: args{
   162  				f: []*flowpb.FlowFilter{
   163  					{SourceIp: []string{"1.1.1.1"}},
   164  				},
   165  				ev: []*v1.Event{
   166  					nil,
   167  					{},
   168  					{Event: &flowpb.Flow{}},
   169  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: ""}}},
   170  				},
   171  			},
   172  			want: []bool{
   173  				false,
   174  				false,
   175  				false,
   176  				false,
   177  			},
   178  		},
   179  		{
   180  			name: "invalid source ip filter",
   181  			args: args{
   182  				f: []*flowpb.FlowFilter{
   183  					{SourceIp: []string{"320.320.320.320"}},
   184  				},
   185  			},
   186  			wantErr: true,
   187  		},
   188  		{
   189  			name: "invalid destination ip filter",
   190  			args: args{
   191  				f: []*flowpb.FlowFilter{
   192  					{DestinationIp: []string{""}},
   193  				},
   194  			},
   195  			wantErr: true,
   196  		},
   197  		{
   198  			name: "invalid snat ip filter",
   199  			args: args{
   200  				f: []*flowpb.FlowFilter{
   201  					{SourceIpXlated: []string{""}},
   202  				},
   203  			},
   204  			wantErr: true,
   205  		},
   206  		{
   207  			name: "source cidr",
   208  			args: args{
   209  				f: []*flowpb.FlowFilter{{SourceIp: []string{"1.1.1.0/24", "f00d::/16"}}},
   210  				ev: []*v1.Event{
   211  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "1.1.1.1", Destination: "10.0.0.2"}}},
   212  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "10.0.0.2", Destination: "1.1.1.1"}}},
   213  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "f00d::a10:0:0:9195", Destination: "ff02::1:ff00:b3e5"}}},
   214  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "ff02::1:ff00:b3e5", Destination: "f00d::a10:0:0:9195"}}},
   215  				},
   216  			},
   217  			want: []bool{
   218  				true,
   219  				false,
   220  				true,
   221  				false,
   222  			},
   223  		},
   224  		{
   225  			name: "destination cidr",
   226  			args: args{
   227  				f: []*flowpb.FlowFilter{{DestinationIp: []string{"1.1.1.0/24", "f00d::/16"}}},
   228  				ev: []*v1.Event{
   229  					{Event: &flowpb.Flow{IP: &flowpb.IP{Destination: "1.1.1.1", Source: "10.0.0.2"}}},
   230  					{Event: &flowpb.Flow{IP: &flowpb.IP{Destination: "10.0.0.2", Source: "1.1.1.1"}}},
   231  					{Event: &flowpb.Flow{IP: &flowpb.IP{Destination: "f00d::a10:0:0:9195", Source: "ff02::1:ff00:b3e5"}}},
   232  					{Event: &flowpb.Flow{IP: &flowpb.IP{Destination: "ff02::1:ff00:b3e5", Source: "f00d::a10:0:0:9195"}}},
   233  				},
   234  			},
   235  			want: []bool{
   236  				true,
   237  				false,
   238  				true,
   239  				false,
   240  			},
   241  		},
   242  		{
   243  			name: "snat cidr",
   244  			args: args{
   245  				f: []*flowpb.FlowFilter{{SourceIpXlated: []string{"1.1.1.0/24", "9bf2::/16"}}},
   246  				ev: []*v1.Event{
   247  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "1.1.1.1", Destination: "1.1.1.2"}}},
   248  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "1.1.1.1", SourceXlated: "1.1.2.1", Destination: "10.0.0.2"}}},
   249  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "1.1.1.1", SourceXlated: "1.1.1.2", Destination: "10.0.0.2"}}},
   250  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "f00d::a10:0:0:9195", Destination: "ff02::1:ff00:b3e5"}}},
   251  					{Event: &flowpb.Flow{IP: &flowpb.IP{Source: "ff02::1:ff00:b3e5", SourceXlated: "9bf2:8d06:6d34:da3b::33c5", Destination: "f00d::a10:0:0:9195"}}},
   252  				},
   253  			},
   254  			want: []bool{
   255  				false,
   256  				false,
   257  				true,
   258  				false,
   259  				true,
   260  			},
   261  		},
   262  		{
   263  			name: "invalid source cidr filter",
   264  			args: args{
   265  				f: []*flowpb.FlowFilter{
   266  					{SourceIp: []string{"1.1.1.1/1234"}},
   267  					{SourceIp: []string{"2001::/1234"}},
   268  				},
   269  			},
   270  			wantErr: true,
   271  		},
   272  		{
   273  			name: "invalid destination cidr filter",
   274  			args: args{
   275  				f: []*flowpb.FlowFilter{
   276  					{DestinationIp: []string{"1.1.1.1/1234"}},
   277  					{DestinationIp: []string{"2001::/1234"}},
   278  				},
   279  			},
   280  			wantErr: true,
   281  		},
   282  		{
   283  			name: "invalid snat cidr filter",
   284  			args: args{
   285  				f: []*flowpb.FlowFilter{
   286  					{SourceIpXlated: []string{"1.1.1.1/1234"}},
   287  					{SourceIpXlated: []string{"2001::/1234"}},
   288  				},
   289  			},
   290  			wantErr: true,
   291  		},
   292  	}
   293  	for _, tt := range tests {
   294  		t.Run(tt.name, func(t *testing.T) {
   295  			fl, err := BuildFilterList(context.Background(), tt.args.f, []OnBuildFilter{&IPFilter{}})
   296  			if (err != nil) != tt.wantErr {
   297  				t.Errorf("BuildFilterList(context.Background(), ) error = %v, wantErr %v", err, tt.wantErr)
   298  				return
   299  			}
   300  			for i, ev := range tt.args.ev {
   301  				if filterResult := fl.MatchOne(ev); filterResult != tt.want[i] {
   302  					t.Errorf("\"%s\" filterResult %d = %v, want %v", tt.name, i, filterResult, tt.want[i])
   303  				}
   304  			}
   305  		})
   306  	}
   307  }
   308  
   309  func TestIPVersionFilter(t *testing.T) {
   310  	allvers := []*v1.Event{
   311  		{Event: &flowpb.Flow{IP: &flowpb.IP{IpVersion: flowpb.IPVersion_IPv4}}},
   312  		{Event: &flowpb.Flow{IP: &flowpb.IP{IpVersion: flowpb.IPVersion_IPv6}}},
   313  		{Event: &flowpb.Flow{IP: &flowpb.IP{IpVersion: flowpb.IPVersion_IP_NOT_USED}}},
   314  	}
   315  	type args struct {
   316  		f  []*flowpb.FlowFilter
   317  		ev []*v1.Event
   318  	}
   319  	tests := []struct {
   320  		name    string
   321  		args    args
   322  		wantErr bool
   323  		want    []bool
   324  	}{
   325  		{
   326  			name: "ipv4 test",
   327  			args: args{
   328  				f: []*flowpb.FlowFilter{
   329  					{IpVersion: []flowpb.IPVersion{flowpb.IPVersion_IPv4}},
   330  				},
   331  				ev: allvers,
   332  			},
   333  			want: []bool{
   334  				true,
   335  				false,
   336  				false,
   337  			},
   338  		},
   339  		{
   340  			name: "ipv6 test",
   341  			args: args{
   342  				f: []*flowpb.FlowFilter{
   343  					{IpVersion: []flowpb.IPVersion{flowpb.IPVersion_IPv6}},
   344  				},
   345  				ev: allvers,
   346  			},
   347  			want: []bool{
   348  				false,
   349  				true,
   350  				false,
   351  			},
   352  		},
   353  		{
   354  			name: "unknown network protocol test",
   355  			args: args{
   356  				f: []*flowpb.FlowFilter{
   357  					{IpVersion: []flowpb.IPVersion{flowpb.IPVersion_IP_NOT_USED}},
   358  				},
   359  				ev: allvers,
   360  			},
   361  			want: []bool{
   362  				false,
   363  				false,
   364  				true,
   365  			},
   366  		},
   367  		{
   368  			name: "both ipv4 and ipv6 allow test",
   369  			args: args{
   370  				f: []*flowpb.FlowFilter{
   371  					{IpVersion: []flowpb.IPVersion{flowpb.IPVersion_IPv4}},
   372  					{IpVersion: []flowpb.IPVersion{flowpb.IPVersion_IPv6}},
   373  				},
   374  				ev: allvers,
   375  			},
   376  			want: []bool{
   377  				true,
   378  				true,
   379  				false,
   380  			},
   381  		},
   382  		{
   383  			name: "all ipv4,ipv6,unknown allow test",
   384  			args: args{
   385  				f: []*flowpb.FlowFilter{
   386  					{IpVersion: []flowpb.IPVersion{flowpb.IPVersion_IPv4}},
   387  					{IpVersion: []flowpb.IPVersion{flowpb.IPVersion_IPv6}},
   388  					{IpVersion: []flowpb.IPVersion{flowpb.IPVersion_IP_NOT_USED}},
   389  				},
   390  				ev: allvers,
   391  			},
   392  			want: []bool{
   393  				true,
   394  				true,
   395  				true,
   396  			},
   397  		},
   398  		{
   399  			name: "test with non-flow event",
   400  			args: args{
   401  				f: []*flowpb.FlowFilter{
   402  					{IpVersion: []flowpb.IPVersion{flowpb.IPVersion_IPv4}},
   403  					{IpVersion: []flowpb.IPVersion{flowpb.IPVersion_IPv6}},
   404  				},
   405  				ev: []*v1.Event{
   406  					{Event: &flowpb.AgentEvent{}},
   407  				},
   408  			},
   409  			want: []bool{
   410  				false,
   411  			},
   412  		},
   413  		{
   414  			name: "test with non-flow event and IP_NOT_USED",
   415  			args: args{
   416  				f: []*flowpb.FlowFilter{
   417  					{IpVersion: []flowpb.IPVersion{flowpb.IPVersion_IP_NOT_USED}},
   418  				},
   419  				ev: []*v1.Event{
   420  					{Event: &flowpb.AgentEvent{}},
   421  				},
   422  			},
   423  			want: []bool{
   424  				false,
   425  			},
   426  		},
   427  	}
   428  	for _, tt := range tests {
   429  		t.Run(tt.name, func(t *testing.T) {
   430  			fl, err := BuildFilterList(context.Background(), tt.args.f, []OnBuildFilter{&IPVersionFilter{}})
   431  			if (err != nil) != tt.wantErr {
   432  				t.Errorf("BuildFilterList(context.Background(), ) error = %v, wantErr %v", err, tt.wantErr)
   433  				return
   434  			}
   435  			for i, ev := range tt.args.ev {
   436  				if filterResult := fl.MatchOne(ev); filterResult != tt.want[i] {
   437  					t.Errorf("\"%s\" filterResult %d = %v, want %v", tt.name, i, filterResult, tt.want[i])
   438  				}
   439  			}
   440  		})
   441  	}
   442  }