github.com/imran-kn/cilium-fork@v1.6.9/pkg/policy/api/cidr.go (about) 1 // Copyright 2016-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 api 16 17 import ( 18 "net" 19 "strings" 20 21 "github.com/cilium/cilium/pkg/ip" 22 "github.com/cilium/cilium/pkg/labels" 23 cidrpkg "github.com/cilium/cilium/pkg/labels/cidr" 24 ) 25 26 // CIDR specifies a block of IP addresses. 27 // Example: 192.0.2.1/32 28 type CIDR string 29 30 // CIDRMatchAll is a []CIDR that matches everything 31 var CIDRMatchAll = []CIDR{CIDR("0.0.0.0/0"), CIDR("::/0")} 32 33 // MatchesAll determines whether the CIDR matches all traffic. 34 func (c *CIDR) MatchesAll() bool { 35 for _, wildcard := range CIDRMatchAll { 36 if *c == wildcard { 37 return true 38 } 39 } 40 return false 41 } 42 43 // CIDRRule is a rule that specifies a CIDR prefix to/from which outside 44 // communication is allowed, along with an optional list of subnets within that 45 // CIDR prefix to/from which outside communication is not allowed. 46 type CIDRRule struct { 47 // CIDR is a CIDR prefix / IP Block. 48 // 49 Cidr CIDR `json:"cidr"` 50 51 // ExceptCIDRs is a list of IP blocks which the endpoint subject to the rule 52 // is not allowed to initiate connections to. These CIDR prefixes should be 53 // contained within Cidr. These exceptions are only applied to the Cidr in 54 // this CIDRRule, and do not apply to any other CIDR prefixes in any other 55 // CIDRRules. 56 // 57 // +optional 58 ExceptCIDRs []CIDR `json:"except,omitempty"` 59 60 // Generated indicates whether the rule was generated based on other rules 61 // or provided by user 62 Generated bool `json:"-"` 63 } 64 65 // String converts the CIDRRule into a human-readable string. 66 func (r CIDRRule) String() string { 67 exceptCIDRs := "" 68 if len(r.ExceptCIDRs) > 0 { 69 exceptCIDRs = "-" + CIDRSlice(r.ExceptCIDRs).String() 70 } 71 return string(r.Cidr) + exceptCIDRs 72 } 73 74 // CIDRSlice is a slice of CIDRs. It allows receiver methods to be defined for 75 // transforming the slice into other convenient forms such as 76 // EndpointSelectorSlice. 77 type CIDRSlice []CIDR 78 79 // GetAsEndpointSelectors returns the provided CIDR slice as a slice of 80 // endpoint selectors 81 func (s CIDRSlice) GetAsEndpointSelectors() EndpointSelectorSlice { 82 // If multiple CIDRs representing reserved:world are in this CIDRSlice, 83 // we only have to add the EndpointSelector representing reserved:world 84 // once. 85 var hasWorldBeenAdded bool 86 slice := EndpointSelectorSlice{} 87 for _, cidr := range s { 88 if cidr.MatchesAll() && !hasWorldBeenAdded { 89 hasWorldBeenAdded = true 90 slice = append(slice, ReservedEndpointSelectors[labels.IDNameWorld]) 91 } 92 lbl, err := cidrpkg.IPStringToLabel(string(cidr)) 93 if err == nil { 94 slice = append(slice, NewESFromLabels(lbl)) 95 } 96 // TODO: Log the error? 97 } 98 99 return slice 100 } 101 102 // StringSlice returns the CIDR slice as a slice of strings. 103 func (s CIDRSlice) StringSlice() []string { 104 result := make([]string, 0, len(s)) 105 for _, c := range s { 106 result = append(result, string(c)) 107 } 108 return result 109 } 110 111 // String converts the CIDRSlice into a human-readable string. 112 func (s CIDRSlice) String() string { 113 if len(s) == 0 { 114 return "" 115 } 116 return "[" + strings.Join(s.StringSlice(), ",") + "]" 117 } 118 119 // CIDRRuleSlice is a slice of CIDRRules. It allows receiver methods to be 120 // defined for transforming the slice into other convenient forms such as 121 // EndpointSelectorSlice. 122 type CIDRRuleSlice []CIDRRule 123 124 // GetAsEndpointSelectors returns the provided CIDRRule slice as a slice of 125 // endpoint selectors 126 func (s CIDRRuleSlice) GetAsEndpointSelectors() EndpointSelectorSlice { 127 cidrs := ComputeResultantCIDRSet(s) 128 return cidrs.GetAsEndpointSelectors() 129 } 130 131 // StringSlice returns the CIDRRuleSlice as a slice of strings. 132 func (s CIDRRuleSlice) StringSlice() []string { 133 result := make([]string, 0, len(s)) 134 for _, c := range s { 135 result = append(result, c.String()) 136 } 137 return result 138 } 139 140 // ComputeResultantCIDRSet converts a slice of CIDRRules into a slice of 141 // individual CIDRs. This expands the cidr defined by each CIDRRule, applies 142 // the CIDR exceptions defined in "ExceptCIDRs", and forms a minimal set of 143 // CIDRs that cover all of the CIDRRules. 144 // 145 // Assumes no error checking is necessary as CIDRRule.Sanitize already does this. 146 func ComputeResultantCIDRSet(cidrs CIDRRuleSlice) CIDRSlice { 147 var allResultantAllowedCIDRs CIDRSlice 148 for _, s := range cidrs { 149 _, allowNet, _ := net.ParseCIDR(string(s.Cidr)) 150 151 var removeSubnets []*net.IPNet 152 for _, t := range s.ExceptCIDRs { 153 _, removeSubnet, _ := net.ParseCIDR(string(t)) 154 removeSubnets = append(removeSubnets, removeSubnet) 155 } 156 resultantAllowedCIDRs, _ := ip.RemoveCIDRs([]*net.IPNet{allowNet}, removeSubnets) 157 158 for _, u := range resultantAllowedCIDRs { 159 allResultantAllowedCIDRs = append(allResultantAllowedCIDRs, CIDR(u.String())) 160 } 161 } 162 return allResultantAllowedCIDRs 163 } 164 165 // IPsToCIDRRules generates CIDRRules for the IPs passed in./ 166 // This function will mark the rule to Generated true by default. 167 func IPsToCIDRRules(ips []net.IP) (cidrRules []CIDRRule) { 168 for _, ip := range ips { 169 rule := CIDRRule{ExceptCIDRs: make([]CIDR, 0)} 170 rule.Generated = true 171 if ip.To4() != nil { 172 rule.Cidr = CIDR(ip.String() + "/32") 173 } else { 174 rule.Cidr = CIDR(ip.String() + "/128") 175 } 176 cidrRules = append(cidrRules, rule) 177 } 178 return cidrRules 179 }