github.com/looshlee/beatles@v0.0.0-20220727174639-742810ab631c/pkg/identity/identity.go (about) 1 // Copyright 2018-2019 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 identity 16 17 import ( 18 "fmt" 19 "net" 20 21 "github.com/cilium/cilium/api/v1/models" 22 "github.com/cilium/cilium/pkg/labels" 23 ) 24 25 // Identity is the representation of the security context for a particular set of 26 // labels. 27 type Identity struct { 28 // Identity's ID. 29 ID NumericIdentity `json:"id"` 30 // Set of labels that belong to this Identity. 31 Labels labels.Labels `json:"labels"` 32 // SHA256 of labels. 33 LabelsSHA256 string `json:"labelsSHA256"` 34 35 // LabelArray contains the same labels as Labels in a form of a list, used 36 // for faster lookup. 37 LabelArray labels.LabelArray `json:"-"` 38 39 // CIDRLabel is the primary identity label when the identity represents 40 // a CIDR. The Labels field will consist of all matching prefixes, e.g. 41 // 10.0.0.0/8 42 // 10.0.0.0/7 43 // 10.0.0.0/6 44 // [...] 45 // reserved:world 46 // 47 // The CIDRLabel field will only contain 10.0.0.0/8 48 CIDRLabel labels.Labels `json:"-"` 49 50 // ReferenceCount counts the number of references pointing to this 51 // identity. This field is used by the owning cache of the identity. 52 ReferenceCount int `json:"-"` 53 } 54 55 // IPIdentityPair is a pairing of an IP and the security identity to which that 56 // IP corresponds. May include an optional Mask which, if present, denotes that 57 // the IP represents a CIDR with the specified Mask. 58 // 59 // WARNING - STABLE API 60 // This structure is written as JSON to the key-value store. Do NOT modify this 61 // structure in ways which are not JSON forward compatible. 62 type IPIdentityPair struct { 63 IP net.IP `json:"IP"` 64 Mask net.IPMask `json:"Mask"` 65 HostIP net.IP `json:"HostIP"` 66 ID NumericIdentity `json:"ID"` 67 Key uint8 `json:"Key"` 68 Metadata string `json:"Metadata"` 69 } 70 71 func NewIdentityFromModel(base *models.Identity) *Identity { 72 if base == nil { 73 return nil 74 } 75 76 id := &Identity{ 77 ID: NumericIdentity(base.ID), 78 Labels: make(labels.Labels), 79 } 80 for _, v := range base.Labels { 81 lbl := labels.ParseLabel(v) 82 id.Labels[lbl.Key] = lbl 83 } 84 id.Sanitize() 85 86 return id 87 } 88 89 // Sanitize takes a partially initialized Identity (for example, deserialized 90 // from json) and reconstitutes the full object from what has been restored. 91 func (id *Identity) Sanitize() { 92 if id.Labels != nil { 93 id.LabelArray = id.Labels.LabelArray() 94 } 95 } 96 97 // GetLabelsSHA256 returns the SHA256 of the labels associated with the 98 // identity. The SHA is calculated if not already cached. 99 func (id *Identity) GetLabelsSHA256() string { 100 if id.LabelsSHA256 == "" { 101 id.LabelsSHA256 = id.Labels.SHA256Sum() 102 } 103 104 return id.LabelsSHA256 105 } 106 107 // StringID returns the identity identifier as string 108 func (id *Identity) StringID() string { 109 return id.ID.StringID() 110 } 111 112 // StringID returns the identity identifier as string 113 func (id *Identity) String() string { 114 return id.ID.StringID() 115 } 116 117 func (id *Identity) GetModel() *models.Identity { 118 if id == nil { 119 return nil 120 } 121 122 ret := &models.Identity{ 123 ID: int64(id.ID), 124 Labels: []string{}, 125 LabelsSHA256: "", 126 } 127 128 for _, v := range id.Labels { 129 ret.Labels = append(ret.Labels, v.String()) 130 } 131 ret.LabelsSHA256 = id.GetLabelsSHA256() 132 return ret 133 } 134 135 // IsReserved returns whether the identity represents a reserved identity 136 // (true), or not (false). 137 func (id *Identity) IsReserved() bool { 138 return LookupReservedIdentity(id.ID) != nil 139 } 140 141 // IsFixed returns whether the identity represents a fixed identity 142 // (true), or not (false). 143 func (id *Identity) IsFixed() bool { 144 return LookupReservedIdentity(id.ID) != nil && IsUserReservedIdentity(id.ID) 145 } 146 147 // IsWellKnown returns whether the identity represents a well known identity 148 // (true), or not (false). 149 func (id *Identity) IsWellKnown() bool { 150 return WellKnown.lookupByNumericIdentity(id.ID) != nil 151 } 152 153 // NewIdentityFromLabelArray creates a new identity 154 func NewIdentityFromLabelArray(id NumericIdentity, lblArray labels.LabelArray) *Identity { 155 var lbls labels.Labels 156 157 if lblArray != nil { 158 lbls = lblArray.Labels() 159 } 160 return &Identity{ID: id, Labels: lbls, LabelArray: lblArray} 161 } 162 163 // NewIdentity creates a new identity 164 func NewIdentity(id NumericIdentity, lbls labels.Labels) *Identity { 165 var lblArray labels.LabelArray 166 167 if lbls != nil { 168 lblArray = lbls.LabelArray() 169 } 170 return &Identity{ID: id, Labels: lbls, LabelArray: lblArray} 171 } 172 173 // IsHost determines whether the IP in the pair represents a host (true) or a 174 // CIDR prefix (false) 175 func (pair *IPIdentityPair) IsHost() bool { 176 return pair.Mask == nil 177 } 178 179 // PrefixString returns the IPIdentityPair's IP as either a host IP in the 180 // format w.x.y.z if 'host' is true, or as a prefix in the format the w.x.y.z/N 181 // if 'host' is false. 182 func (pair *IPIdentityPair) PrefixString() string { 183 var suffix string 184 if !pair.IsHost() { 185 var ones int 186 if pair.Mask == nil { 187 if pair.IP.To4() != nil { 188 ones = net.IPv4len 189 } else { 190 ones = net.IPv6len 191 } 192 } else { 193 ones, _ = pair.Mask.Size() 194 } 195 suffix = fmt.Sprintf("/%d", ones) 196 } 197 return fmt.Sprintf("%s%s", pair.IP.String(), suffix) 198 } 199 200 // RequiresGlobalIdentity returns true if the label combination requires a 201 // global identity 202 func RequiresGlobalIdentity(lbls labels.Labels) bool { 203 needsGlobal := true 204 205 for _, label := range lbls { 206 switch label.Source { 207 case labels.LabelSourceCIDR, labels.LabelSourceReserved: 208 needsGlobal = false 209 default: 210 return true 211 } 212 } 213 214 return needsGlobal 215 }