github.com/cilium/cilium@v1.16.2/pkg/hubble/filters/fqdn.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Hubble 3 4 package filters 5 6 import ( 7 "context" 8 "fmt" 9 "regexp" 10 11 flowpb "github.com/cilium/cilium/api/v1/flow" 12 v1 "github.com/cilium/cilium/pkg/hubble/api/v1" 13 ) 14 15 func sourceFQDN(ev *v1.Event) []string { 16 return ev.GetFlow().GetSourceNames() 17 } 18 19 func destinationFQDN(ev *v1.Event) []string { 20 return ev.GetFlow().GetDestinationNames() 21 } 22 23 func filterByFQDNs(fqdnPatterns []string, getFQDNs func(*v1.Event) []string) (FilterFunc, error) { 24 fqdnRegexp, err := compileFQDNPattern(fqdnPatterns) 25 if err != nil { 26 return nil, err 27 } 28 29 return func(ev *v1.Event) bool { 30 names := getFQDNs(ev) 31 if len(names) == 0 { 32 return false 33 } 34 35 for _, name := range names { 36 if fqdnRegexp.MatchString(name) { 37 return true 38 } 39 } 40 41 return false 42 }, nil 43 } 44 45 // filterByDNSQueries returns a FilterFunc that filters a flow by L7.DNS.query field. 46 // The filter function returns true if and only if the DNS query field matches any of 47 // the regular expressions. 48 func filterByDNSQueries(queryPatterns []string) (FilterFunc, error) { 49 queries := make([]*regexp.Regexp, 0, len(queryPatterns)) 50 for _, pattern := range queryPatterns { 51 query, err := regexp.Compile(pattern) 52 if err != nil { 53 return nil, fmt.Errorf("failed to compile regexp: %w", err) 54 } 55 queries = append(queries, query) 56 } 57 return func(ev *v1.Event) bool { 58 dns := ev.GetFlow().GetL7().GetDns() 59 if dns == nil { 60 return false 61 } 62 for _, query := range queries { 63 if query.MatchString(dns.Query) { 64 return true 65 } 66 } 67 return false 68 }, nil 69 } 70 71 // FQDNFilter implements filtering based on FQDN information 72 type FQDNFilter struct{} 73 74 // OnBuildFilter builds a FQDN filter 75 func (f *FQDNFilter) OnBuildFilter(ctx context.Context, ff *flowpb.FlowFilter) ([]FilterFunc, error) { 76 var fs []FilterFunc 77 78 if ff.GetSourceFqdn() != nil { 79 ff, err := filterByFQDNs(ff.GetSourceFqdn(), sourceFQDN) 80 if err != nil { 81 return nil, err 82 } 83 fs = append(fs, ff) 84 } 85 86 if ff.GetDestinationFqdn() != nil { 87 ff, err := filterByFQDNs(ff.GetDestinationFqdn(), destinationFQDN) 88 if err != nil { 89 return nil, err 90 } 91 fs = append(fs, ff) 92 } 93 94 if ff.GetDnsQuery() != nil { 95 dnsFilters, err := filterByDNSQueries(ff.GetDnsQuery()) 96 if err != nil { 97 return nil, fmt.Errorf("invalid DNS query filter: %w", err) 98 } 99 fs = append(fs, dnsFilters) 100 } 101 102 return fs, nil 103 }