github.com/elfadel/cilium@v1.6.12/pkg/fqdn/helpers.go (about) 1 // Copyright 2018 Authors of Cilium 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package fqdn 16 17 import ( 18 "net" 19 "regexp" 20 "strings" 21 22 "github.com/cilium/cilium/pkg/fqdn/matchpattern" 23 "github.com/cilium/cilium/pkg/ip" 24 "github.com/cilium/cilium/pkg/policy/api" 25 "github.com/miekg/dns" 26 "github.com/sirupsen/logrus" 27 ) 28 29 // mapSelectorsToIPs iterates through a set of FQDNSelectors and evalutes whether 30 // they match the DNS Names in the cache. If so, the set of IPs which the cache 31 // maintains as mapping to each DNS Name are mapped to the matching FQDNSelector. 32 // Returns the mapping of DNSName to set of IPs which back said DNS name, the 33 // set of FQDNSelectors which do not map to any IPs, and the set of 34 // FQDNSelectors mapping to a set of IPs. 35 func mapSelectorsToIPs(fqdnSelectors map[api.FQDNSelector]struct{}, cache *DNSCache) (selectorsMissingIPs []api.FQDNSelector, selectorIPMapping map[api.FQDNSelector][]net.IP) { 36 missing := make(map[api.FQDNSelector]struct{}) // a set to dedup missing dnsNames 37 selectorIPMapping = make(map[api.FQDNSelector][]net.IP) 38 39 log.WithField("fqdnSelectors", fqdnSelectors).Debug("mapSelectorsToIPs") 40 41 // Map each FQDNSelector to set of CIDRs 42 for ToFQDN := range fqdnSelectors { 43 ipsSelected := make([]net.IP, 0) 44 // lookup matching DNS names 45 if len(ToFQDN.MatchName) > 0 { 46 dnsName := prepareMatchName(ToFQDN.MatchName) 47 lookupIPs := cache.Lookup(dnsName) 48 49 // Mark this FQDNSelector as having no IPs corresponding to it. 50 // FQDNSelectors are guaranteed to have only their MatchName OR 51 // their MatchPattern set (having both set is invalid per 52 // sanitization of FQDNSelectors). 53 if len(lookupIPs) == 0 { 54 missing[ToFQDN] = struct{}{} 55 } 56 57 log.WithFields(logrus.Fields{ 58 "DNSName": dnsName, 59 "IPs": lookupIPs, 60 "matchName": ToFQDN.MatchName, 61 }).Debug("Emitting matching DNS Name -> IPs for FQDNSelector") 62 ipsSelected = append(ipsSelected, lookupIPs...) 63 } 64 65 if len(ToFQDN.MatchPattern) > 0 { 66 // lookup matching DNS names 67 dnsPattern := matchpattern.Sanitize(ToFQDN.MatchPattern) 68 patternREStr := matchpattern.ToRegexp(dnsPattern) 69 var ( 70 err error 71 patternRE *regexp.Regexp 72 ) 73 74 if patternRE, err = regexp.Compile(patternREStr); err != nil { 75 log.WithError(err).Error("Error compiling matchPattern") 76 } 77 lookupIPs := cache.LookupByRegexp(patternRE) 78 79 // Mark this pattern missing; it will be unmarked in the loop below 80 missing[ToFQDN] = struct{}{} 81 82 for name, ips := range lookupIPs { 83 if len(ips) > 0 { 84 log.WithFields(logrus.Fields{ 85 "DNSName": name, 86 "IPs": ips, 87 "matchPattern": ToFQDN.MatchPattern, 88 }).Debug("Emitting matching DNS Name -> IPs for FQDNSelector") 89 delete(missing, ToFQDN) 90 ipsSelected = append(ipsSelected, ips...) 91 } 92 } 93 } 94 95 ips := ip.KeepUniqueIPs(ipsSelected) 96 if len(ips) > 0 { 97 selectorIPMapping[ToFQDN] = ips 98 } 99 } 100 101 for dnsName := range missing { 102 selectorsMissingIPs = append(selectorsMissingIPs, dnsName) 103 } 104 return selectorsMissingIPs, selectorIPMapping 105 } 106 107 // sortedIPsAreEqual compares two lists of sorted IPs. If any differ it returns 108 // false. 109 func sortedIPsAreEqual(a, b []net.IP) bool { 110 // the IP set is definitely different if the lengths are different 111 if len(a) != len(b) { 112 return false 113 } 114 115 // lengths are equal, so each member in one set must be in the other 116 // Note: we sorted fullNewIPs above, and sorted oldIPs when they were 117 // inserted in this function, previously. 118 // If any IPs at the same index differ, updated = true. 119 for i := range a { 120 if !a[i].Equal(b[i]) { 121 return false 122 } 123 } 124 return true 125 } 126 127 // prepareMatchName ensures a ToFQDNs.matchName field is used consistently. 128 func prepareMatchName(matchName string) string { 129 return strings.ToLower(dns.Fqdn(matchName)) 130 } 131 132 // KeepUniqueNames it gets a array of strings and return a new array of strings 133 // with the unique names. 134 func KeepUniqueNames(names []string) []string { 135 result := []string{} 136 entries := map[string]bool{} 137 138 for _, item := range names { 139 if _, ok := entries[item]; ok { 140 continue 141 } 142 entries[item] = true 143 result = append(result, item) 144 } 145 return result 146 }