github.com/cilium/cilium@v1.16.2/pkg/policy/api/cidr_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package api
     5  
     6  import (
     7  	"regexp"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/cilium/cilium/pkg/labels"
    13  	"github.com/cilium/cilium/pkg/option"
    14  )
    15  
    16  func TestGetAsEndpointSelectors(t *testing.T) {
    17  	world := labels.ParseLabelArray("reserved:world")
    18  
    19  	labelWorld := labels.ParseSelectLabel("reserved:world")
    20  	esWorld := NewESFromLabels(labelWorld)
    21  
    22  	labelWorldIPv4 := labels.ParseSelectLabel("reserved:world-ipv4")
    23  	esWorldIPv4 := NewESFromLabels(labelWorldIPv4)
    24  
    25  	labelWorldIPv6 := labels.ParseSelectLabel("reserved:world-ipv6")
    26  	esWorldIPv6 := NewESFromLabels(labelWorldIPv6)
    27  
    28  	labelAllV4, err := labels.IPStringToLabel("0.0.0.0/0")
    29  	require.Nil(t, err)
    30  	v4World := NewESFromLabels(labelAllV4)
    31  
    32  	labelAllV6, err := labels.IPStringToLabel("::/0")
    33  	require.Nil(t, err)
    34  	v6World := NewESFromLabels(labelAllV6)
    35  
    36  	labelOtherCIDR, err := labels.IPStringToLabel("192.168.128.0/24")
    37  	require.Nil(t, err)
    38  	esOtherCIDR := NewESFromLabels(labelOtherCIDR)
    39  
    40  	tt := []struct {
    41  		name              string
    42  		cidrs             CIDRSlice
    43  		expectedSelectors EndpointSelectorSlice
    44  		matchesWorld,
    45  		enableIPv4, enableIPv6 bool
    46  	}{
    47  		{
    48  			name: "ipv4 dualstack",
    49  			cidrs: CIDRSlice{
    50  				"0.0.0.0/0",
    51  			},
    52  			expectedSelectors: EndpointSelectorSlice{
    53  				v4World,
    54  				esWorldIPv4,
    55  			},
    56  			matchesWorld: false,
    57  			enableIPv4:   true,
    58  			enableIPv6:   true,
    59  		},
    60  		{
    61  			name: "ipv6 dualstack",
    62  			cidrs: CIDRSlice{
    63  				"::/0",
    64  			},
    65  			expectedSelectors: EndpointSelectorSlice{
    66  				v6World,
    67  				esWorldIPv6,
    68  			},
    69  			matchesWorld: false,
    70  			enableIPv4:   true,
    71  			enableIPv6:   true,
    72  		},
    73  		{
    74  			name: "ipv4 and ipv6 dualstack",
    75  			cidrs: CIDRSlice{
    76  				"0.0.0.0/0",
    77  				"::/0",
    78  				"192.168.128.10/24",
    79  			},
    80  			expectedSelectors: EndpointSelectorSlice{
    81  				v4World,
    82  				v6World,
    83  				esOtherCIDR,
    84  				esWorld,
    85  				esWorldIPv4,
    86  				esWorldIPv6,
    87  			},
    88  			matchesWorld: true,
    89  			enableIPv4:   true,
    90  			enableIPv6:   true,
    91  		},
    92  		{
    93  			name: "ipv4 in ipv4 only",
    94  			cidrs: CIDRSlice{
    95  				"0.0.0.0/0",
    96  			},
    97  			expectedSelectors: EndpointSelectorSlice{
    98  				v4World,
    99  				esWorld,
   100  			},
   101  			matchesWorld: true,
   102  			enableIPv4:   true,
   103  			enableIPv6:   false,
   104  		},
   105  		{
   106  			name: "ipv6 in ipv4 only",
   107  			cidrs: CIDRSlice{
   108  				"::/0",
   109  			},
   110  			expectedSelectors: EndpointSelectorSlice{
   111  				v6World,
   112  			},
   113  			matchesWorld: false,
   114  			enableIPv4:   true,
   115  			enableIPv6:   false,
   116  		},
   117  		{
   118  			name: "ipv4 in ipv6 only",
   119  			cidrs: CIDRSlice{
   120  				"0.0.0.0/0",
   121  			},
   122  			expectedSelectors: EndpointSelectorSlice{
   123  				v4World,
   124  			},
   125  			matchesWorld: false,
   126  			enableIPv4:   false,
   127  			enableIPv6:   true,
   128  		},
   129  		{
   130  			name: "ipv6 in ipv6 only",
   131  			cidrs: CIDRSlice{
   132  				"::/0",
   133  			},
   134  			expectedSelectors: EndpointSelectorSlice{
   135  				v6World,
   136  				esWorld,
   137  			},
   138  			matchesWorld: true,
   139  			enableIPv4:   false,
   140  			enableIPv6:   true,
   141  		},
   142  	}
   143  
   144  	for _, test := range tt {
   145  		t.Logf("running test %s:", test.name)
   146  		option.Config.EnableIPv6 = test.enableIPv6
   147  		option.Config.EnableIPv4 = test.enableIPv4
   148  		result := test.cidrs.GetAsEndpointSelectors()
   149  		require.Equal(t, test.matchesWorld, result.Matches(world))
   150  		require.EqualValues(t, test.expectedSelectors, result)
   151  	}
   152  	option.Config.EnableIPv4 = true
   153  	option.Config.EnableIPv6 = true
   154  }
   155  
   156  const CIDRRegex = `^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\/([0-9]|[1-2][0-9]|3[0-2])$|^s*((([0-9A-Fa-f]{1,4}:){7}(:|([0-9A-Fa-f]{1,4})))|(([0-9A-Fa-f]{1,4}:){6}:([0-9A-Fa-f]{1,4})?)|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){0,1}):([0-9A-Fa-f]{1,4})?))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){0,2}):([0-9A-Fa-f]{1,4})?))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){0,3}):([0-9A-Fa-f]{1,4})?))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){0,4}):([0-9A-Fa-f]{1,4})?))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){0,5}):([0-9A-Fa-f]{1,4})?))|(:(:|((:[0-9A-Fa-f]{1,4}){1,7}))))(%.+)?s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$`
   157  
   158  func TestCIDRRegex(t *testing.T) {
   159  	reg := regexp.MustCompile(CIDRRegex)
   160  
   161  	goodCIDRs := []string{
   162  		"192.0.2.3/32",
   163  		"192.0.2.0/24",
   164  		"0.0.0.0/0",
   165  		"::/0",
   166  		"::cafe/128",
   167  		"::f00d:cafe/128",
   168  		"0:0:0:0:0:0:0:cafe/128",
   169  		"cafe:cafe:cafe:cafe:cafe:cafe:cafe:cafe/128",
   170  		"bad:f00d:cafe:0:0:0:0:add/64",
   171  		"bad:f00d:cafe::bad/64",
   172  		"f00d::/64",
   173  		"f00d::0:0/120",
   174  		"f00d:cafe::1:2/120",
   175  	}
   176  
   177  continueTest:
   178  	for _, input := range goodCIDRs {
   179  		if matched := reg.MatchString(input); matched {
   180  			continue continueTest
   181  		}
   182  		// The below is always false, valid CIDR prefixes should
   183  		// always skip this by continuing in the above loop.
   184  		require.Equal(t, "failed to match CIDR.OneOf[*].Pattern", input)
   185  	}
   186  
   187  	badCIDRs := []string{
   188  		"192.0.2.3",
   189  		"192.0.2.3/",
   190  		"abcdef",
   191  		"0.0.0.0/0/0",
   192  		"::",
   193  		":",
   194  		":/",
   195  		"0:0",
   196  		"::cafe/128/12",
   197  		"abc:def",
   198  		"abc:def/64",
   199  		"f00d::/",
   200  		"f00d::0:0",
   201  		"bad.f00d.cafe.0.0.0.0.add/20",
   202  		"::192.0.2.3/128",
   203  		"::ffff:192.0.2.3/128",
   204  		"abcd:192.0.2.3/128",
   205  		":abcd:192.0.2.3/128",
   206  		"abcd::192.0.2.3/128",
   207  		":abcd::192.0.2.3/128",
   208  		"bad::f00d::cafe/1",
   209  		":bad::f00d::cafe/1",
   210  		"::bad::f00d::cafe/1",
   211  		"::bad::food::cafe/1",
   212  	}
   213  
   214  	for _, input := range badCIDRs {
   215  		if matched := reg.MatchString(input); matched {
   216  			// The below is always false, invalid CIDR
   217  			// prefixes are not supposed to match the regex.
   218  			require.Equal(t, "unexpectedly matched CIDR.OneOf[*].Pattern", input)
   219  		}
   220  	}
   221  }