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 }