github.com/cilium/cilium@v1.16.2/pkg/identity/identitymanager/manager.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package identitymanager 5 6 import ( 7 "github.com/sirupsen/logrus" 8 9 "github.com/cilium/cilium/api/v1/models" 10 "github.com/cilium/cilium/pkg/identity" 11 "github.com/cilium/cilium/pkg/identity/model" 12 "github.com/cilium/cilium/pkg/lock" 13 "github.com/cilium/cilium/pkg/logging/logfields" 14 ) 15 16 var ( 17 // GlobalIdentityManager is a singleton instance of an IdentityManager, used 18 // for easy updating / tracking lifecycles of identities on the local node 19 // without having to pass around a specific instance of an IdentityManager 20 // throughout Cilium. 21 GlobalIdentityManager = NewIdentityManager() 22 ) 23 24 // IdentityManager caches information about a set of identities, currently a 25 // reference count of how many users there are for each identity. 26 type IdentityManager struct { 27 mutex lock.RWMutex 28 identities map[identity.NumericIdentity]*identityMetadata 29 observers map[Observer]struct{} 30 } 31 32 type identityMetadata struct { 33 identity *identity.Identity 34 refCount uint 35 } 36 37 // NewIdentityManager returns an initialized IdentityManager. 38 func NewIdentityManager() *IdentityManager { 39 return &IdentityManager{ 40 identities: make(map[identity.NumericIdentity]*identityMetadata), 41 observers: make(map[Observer]struct{}), 42 } 43 } 44 45 // Add inserts the identity into the GlobalIdentityManager. 46 func Add(identity *identity.Identity) { 47 GlobalIdentityManager.Add(identity) 48 } 49 50 // Remove deletes the identity from the GlobalIdentityManager. 51 func Remove(identity *identity.Identity) { 52 GlobalIdentityManager.Remove(identity) 53 } 54 55 // RemoveAll deletes all identities from the GlobalIdentityManager. 56 func RemoveAll() { 57 GlobalIdentityManager.RemoveAll() 58 } 59 60 // Add inserts the identity into the identity manager. If the identity is 61 // already in the identity manager, the reference count for the identity is 62 // incremented. 63 func (idm *IdentityManager) Add(identity *identity.Identity) { 64 log.WithFields(logrus.Fields{ 65 logfields.Identity: identity, 66 }).Debug("Adding identity to the identity manager") 67 68 idm.mutex.Lock() 69 defer idm.mutex.Unlock() 70 idm.add(identity) 71 } 72 73 func (idm *IdentityManager) add(identity *identity.Identity) { 74 75 if identity == nil { 76 return 77 } 78 79 idMeta, exists := idm.identities[identity.ID] 80 if !exists { 81 idm.identities[identity.ID] = &identityMetadata{ 82 identity: identity, 83 refCount: 1, 84 } 85 for o := range idm.observers { 86 o.LocalEndpointIdentityAdded(identity) 87 } 88 89 } else { 90 idMeta.refCount++ 91 } 92 } 93 94 // RemoveOldAddNew removes old from the identity manager and inserts new 95 // into the IdentityManager. 96 // Caller must have previously added the old identity with Add(). 97 // This is a no-op if both identities have the same numeric ID. 98 func (idm *IdentityManager) RemoveOldAddNew(old, new *identity.Identity) { 99 idm.mutex.Lock() 100 defer idm.mutex.Unlock() 101 102 if old == nil && new == nil { 103 return 104 } 105 // The host endpoint will always retain its reserved ID, but its labels may 106 // change so we need to update its identity. 107 if old != nil && new != nil && old.ID == new.ID && new.ID != identity.ReservedIdentityHost { 108 return 109 } 110 111 log.WithFields(logrus.Fields{ 112 "old": old, 113 "new": new, 114 }).Debug("removing old and adding new identity") 115 116 idm.remove(old) 117 idm.add(new) 118 } 119 120 // RemoveOldAddNew removes old from and inserts new into the 121 // GlobalIdentityManager. 122 func RemoveOldAddNew(old, new *identity.Identity) { 123 GlobalIdentityManager.RemoveOldAddNew(old, new) 124 } 125 126 // RemoveAll removes all identities. 127 func (idm *IdentityManager) RemoveAll() { 128 idm.mutex.Lock() 129 defer idm.mutex.Unlock() 130 131 for id := range idm.identities { 132 idm.remove(idm.identities[id].identity) 133 } 134 } 135 136 // Remove deletes the identity from the identity manager. If the identity is 137 // already in the identity manager, the reference count for the identity is 138 // decremented. If the identity is not in the cache, this is a no-op. If the 139 // ref count becomes zero, the identity is removed from the cache. 140 func (idm *IdentityManager) Remove(identity *identity.Identity) { 141 log.WithFields(logrus.Fields{ 142 logfields.Identity: identity, 143 }).Debug("Removing identity from the identity manager") 144 145 idm.mutex.Lock() 146 defer idm.mutex.Unlock() 147 idm.remove(identity) 148 } 149 150 func (idm *IdentityManager) remove(identity *identity.Identity) { 151 152 if identity == nil { 153 return 154 } 155 156 idMeta, exists := idm.identities[identity.ID] 157 if !exists { 158 log.WithFields(logrus.Fields{ 159 logfields.Identity: identity, 160 }).Error("removing identity not added to the identity manager!") 161 return 162 } 163 idMeta.refCount-- 164 if idMeta.refCount == 0 { 165 delete(idm.identities, identity.ID) 166 for o := range idm.observers { 167 o.LocalEndpointIdentityRemoved(identity) 168 } 169 } 170 171 } 172 173 // GetIdentityModels returns the API representation of the IdentityManager. 174 func (idm *IdentityManager) GetIdentityModels() []*models.IdentityEndpoints { 175 idm.mutex.RLock() 176 defer idm.mutex.RUnlock() 177 178 identities := make([]*models.IdentityEndpoints, 0, len(idm.identities)) 179 180 for _, v := range idm.identities { 181 identities = append(identities, &models.IdentityEndpoints{ 182 Identity: model.CreateModel(v.identity), 183 RefCount: int64(v.refCount), 184 }) 185 } 186 187 return identities 188 } 189 190 func (idm *IdentityManager) subscribe(o Observer) { 191 idm.mutex.Lock() 192 defer idm.mutex.Unlock() 193 idm.observers[o] = struct{}{} 194 } 195 196 // GetIdentityModels returns the API model of all identities in the 197 // GlobalIdentityManager. 198 func GetIdentityModels() []*models.IdentityEndpoints { 199 return GlobalIdentityManager.GetIdentityModels() 200 } 201 202 // IdentitiesModel is a wrapper so that we can implement the sort.Interface 203 // to sort the slice by ID 204 type IdentitiesModel []*models.IdentityEndpoints 205 206 // Less returns true if the element in index `i` is lower than the element 207 // in index `j` 208 func (s IdentitiesModel) Less(i, j int) bool { 209 return s[i].Identity.ID < s[j].Identity.ID 210 } 211 212 // Subscribe adds the specified Observer to the global identity manager, to be 213 // notified upon changes to local identity usage. 214 func Subscribe(o Observer) { 215 GlobalIdentityManager.subscribe(o) 216 }