github.com/cilium/cilium@v1.16.2/pkg/fqdn/dnsproxy/helpers_test.go (about)

     1  // SPDX-License-Identifier: Apache-2.0
     2  // Copyright Authors of Cilium
     3  
     4  package dnsproxy
     5  
     6  import (
     7  	"regexp"
     8  	"testing"
     9  
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/cilium/cilium/pkg/defaults"
    13  	"github.com/cilium/cilium/pkg/fqdn/dns"
    14  	"github.com/cilium/cilium/pkg/fqdn/re"
    15  	"github.com/cilium/cilium/pkg/fqdn/restore"
    16  	"github.com/cilium/cilium/pkg/identity"
    17  	"github.com/cilium/cilium/pkg/labels"
    18  	"github.com/cilium/cilium/pkg/policy"
    19  	"github.com/cilium/cilium/pkg/policy/api"
    20  	"github.com/cilium/cilium/pkg/u8proto"
    21  )
    22  
    23  const (
    24  	udpProto = uint8(u8proto.UDP)
    25  	tcpProto = uint8(u8proto.TCP)
    26  )
    27  
    28  func TestSetPortRulesForID(t *testing.T) {
    29  	re.InitRegexCompileLRU(1)
    30  	rules := policy.L7DataMap{}
    31  	epID := uint64(1)
    32  	pea := perEPAllow{}
    33  	cache := make(regexCache)
    34  	udpProtoPort8053 := restore.MakeV2PortProto(8053, udpProto)
    35  
    36  	rules[new(MockCachedSelector)] = &policy.PerSelectorPolicy{
    37  		L7Rules: api.L7Rules{
    38  			DNS: []api.PortRuleDNS{
    39  				{MatchName: "cilium.io."},
    40  				{MatchPattern: "*.cilium.io."},
    41  			},
    42  		},
    43  	}
    44  
    45  	err := pea.setPortRulesForID(cache, epID, udpProtoPort8053, rules)
    46  	require.Equal(t, nil, err)
    47  	require.Equal(t, 1, len(cache))
    48  
    49  	selector2 := new(MockCachedSelector)
    50  	rules[selector2] = &policy.PerSelectorPolicy{
    51  		L7Rules: api.L7Rules{
    52  			DNS: []api.PortRuleDNS{
    53  				{MatchName: "cilium2.io."},
    54  				{MatchPattern: "*.cilium2.io."},
    55  				{MatchPattern: "*.cilium3.io."},
    56  			},
    57  		},
    58  	}
    59  
    60  	err = pea.setPortRulesForID(cache, epID, udpProtoPort8053, rules)
    61  	require.Equal(t, nil, err)
    62  	require.Equal(t, 2, len(cache))
    63  
    64  	delete(rules, selector2)
    65  	err = pea.setPortRulesForID(cache, epID, udpProtoPort8053, rules)
    66  	require.Equal(t, nil, err)
    67  	require.Equal(t, 1, len(cache))
    68  
    69  	err = pea.setPortRulesForID(cache, epID, udpProtoPort8053, nil)
    70  	require.Equal(t, nil, err)
    71  	require.Equal(t, 0, len(cache))
    72  
    73  	rules[selector2] = &policy.PerSelectorPolicy{
    74  		L7Rules: api.L7Rules{
    75  			DNS: []api.PortRuleDNS{
    76  				{MatchName: "cilium2.io."},
    77  				{MatchPattern: "*.cilium2.io."},
    78  				{MatchPattern: "-invalid-pattern("},
    79  				{MatchPattern: "*.cilium3.io."},
    80  			},
    81  		},
    82  	}
    83  	err = pea.setPortRulesForID(cache, epID, udpProtoPort8053, rules)
    84  
    85  	require.Error(t, err)
    86  	require.Equal(t, 0, len(cache))
    87  }
    88  
    89  func TestSetPortRulesForIDFromUnifiedFormat(t *testing.T) {
    90  	re.InitRegexCompileLRU(1)
    91  	rules := make(CachedSelectorREEntry)
    92  	epID := uint64(1)
    93  	pea := perEPAllow{}
    94  	cache := make(regexCache)
    95  	udpProtoPort8053 := restore.MakeV2PortProto(8053, udpProto)
    96  	rules[new(MockCachedSelector)] = regexp.MustCompile("^.*[.]cilium[.]io$")
    97  	rules[new(MockCachedSelector)] = regexp.MustCompile("^.*[.]cilium[.]io$")
    98  
    99  	err := pea.setPortRulesForIDFromUnifiedFormat(cache, epID, udpProtoPort8053, rules)
   100  	require.Equal(t, nil, err)
   101  	require.Equal(t, 1, len(cache))
   102  
   103  	selector2 := new(MockCachedSelector)
   104  	rules[selector2] = regexp.MustCompile("^sub[.]cilium[.]io")
   105  	err = pea.setPortRulesForIDFromUnifiedFormat(cache, epID, udpProtoPort8053, rules)
   106  	require.Equal(t, nil, err)
   107  	require.Equal(t, 2, len(cache))
   108  
   109  	delete(rules, selector2)
   110  	err = pea.setPortRulesForIDFromUnifiedFormat(cache, epID, udpProtoPort8053, rules)
   111  	require.Equal(t, nil, err)
   112  	require.Equal(t, 1, len(cache))
   113  
   114  	err = pea.setPortRulesForIDFromUnifiedFormat(cache, epID, udpProtoPort8053, nil)
   115  	require.Equal(t, nil, err)
   116  	require.Equal(t, 0, len(cache))
   117  
   118  	delete(rules, selector2)
   119  	err = pea.setPortRulesForIDFromUnifiedFormat(cache, epID, udpProtoPort8053, rules)
   120  	require.Equal(t, nil, err)
   121  	require.Equal(t, 1, len(cache))
   122  
   123  	err = pea.setPortRulesForIDFromUnifiedFormat(cache, epID, udpProtoPort8053, nil)
   124  	require.Equal(t, nil, err)
   125  	require.Equal(t, 0, len(cache))
   126  }
   127  
   128  func TestGeneratePattern(t *testing.T) {
   129  	l7 := &policy.PerSelectorPolicy{
   130  		L7Rules: api.L7Rules{DNS: []api.PortRuleDNS{
   131  			{MatchName: "example.name."},
   132  			{MatchName: "example.com."},
   133  			{MatchName: "demo.io."},
   134  			{MatchName: "demoo.tld."},
   135  			{MatchPattern: "*pattern.com"},
   136  			{MatchPattern: "*.*.*middle.*"},
   137  		}},
   138  	}
   139  	matching := []string{"example.name.", "example.com.", "demo.io.", "demoo.tld.", "testpattern.com.", "pattern.com.", "a.b.cmiddle.io."}
   140  	notMatching := []string{"eexample.name.", "eexample.com.", "vdemo.io.", "demo.ioo.", "emoo.tld.", "test.ppattern.com.", "b.cmiddle.io."}
   141  
   142  	re.InitRegexCompileLRU(defaults.FQDNRegexCompileLRUSize)
   143  	pattern := GeneratePattern(l7)
   144  
   145  	regex, err := re.CompileRegex(pattern)
   146  	require.Equal(t, nil, err)
   147  
   148  	for _, fqdn := range matching {
   149  		require.Truef(t, regex.MatchString(fqdn), "expected fqdn %q to match, but it did not", fqdn)
   150  	}
   151  	for _, fqdn := range notMatching {
   152  		require.Falsef(t, regex.MatchString(fqdn), "expected fqdn %q to not match, but it did", fqdn)
   153  	}
   154  
   155  	pattern = GeneratePattern(
   156  		&policy.PerSelectorPolicy{
   157  			L7Rules: api.L7Rules{DNS: []api.PortRuleDNS{
   158  				{MatchPattern: "domo.io."},
   159  				{MatchPattern: "*"},
   160  			}},
   161  		})
   162  
   163  	regex, err = re.CompileRegex(pattern)
   164  	require.Equal(t, nil, err)
   165  
   166  	// Ensure all fqdns match a policy with a wildcard
   167  	for _, fqdn := range append(matching, notMatching...) {
   168  		require.Truef(t, regex.MatchString(fqdn), "expected fqdn %q to match with wildcard policy, but it did not", fqdn)
   169  	}
   170  
   171  	pattern = GeneratePattern(&policy.PerSelectorPolicy{
   172  		L7Rules: api.L7Rules{},
   173  	})
   174  
   175  	regex, err = re.CompileRegex(pattern)
   176  	require.Equal(t, nil, err)
   177  
   178  	// Ensure all fqdns match a policy without any dns-rules
   179  	for _, fqdn := range append(matching, notMatching...) {
   180  		require.Truef(t, regex.MatchString(fqdn), "expected fqdn %q to match with wildcard policy, but it did not", fqdn)
   181  	}
   182  
   183  	pattern = GeneratePattern(&policy.PerSelectorPolicy{
   184  		L7Rules: api.L7Rules{DNS: []api.PortRuleDNS{}},
   185  	})
   186  	regex, err = re.CompileRegex(pattern)
   187  	require.Equal(t, nil, err)
   188  
   189  	// Ensure all fqdns match a policy without any dns-rules
   190  	for _, fqdn := range append(matching, notMatching...) {
   191  		require.Truef(t, regex.MatchString(fqdn), "expected fqdn %q to match with wildcard policy, but it did not", fqdn)
   192  	}
   193  }
   194  
   195  func TestGeneratePatternTrailingDot(t *testing.T) {
   196  	dnsName := "example.name"
   197  	dnsPattern := "*.example.name"
   198  	generatePattern := func(name, pattern string) string {
   199  		l7 := &policy.PerSelectorPolicy{
   200  			L7Rules: api.L7Rules{DNS: []api.PortRuleDNS{
   201  				{MatchName: name},
   202  				{MatchPattern: pattern},
   203  			}},
   204  		}
   205  		return GeneratePattern(l7)
   206  
   207  	}
   208  	require.EqualValues(t, generatePattern(dns.FQDN(dnsPattern), dns.FQDN(dnsName)), generatePattern(dnsPattern, dnsName))
   209  
   210  }
   211  
   212  type MockCachedSelector struct {
   213  	key string
   214  }
   215  
   216  func (m MockCachedSelector) GetSelections() identity.NumericIdentitySlice {
   217  	return nil
   218  }
   219  
   220  func (m MockCachedSelector) GetMetadataLabels() labels.LabelArray {
   221  	panic("implement me")
   222  }
   223  
   224  func (m MockCachedSelector) Selects(_ identity.NumericIdentity) bool {
   225  	return false
   226  }
   227  
   228  func (m MockCachedSelector) IsWildcard() bool {
   229  	return false
   230  }
   231  
   232  func (m MockCachedSelector) IsNone() bool {
   233  	return false
   234  }
   235  
   236  func (m MockCachedSelector) String() string {
   237  	return m.key
   238  }