github.com/kaisenlinux/docker.io@v0.0.0-20230510090727-ea55db55fac7/swarmkit/manager/keymanager/keymanager.go (about) 1 package keymanager 2 3 // keymanager does the allocation, rotation and distribution of symmetric 4 // keys to the agents. This is to securely bootstrap network communication 5 // between agents. It can be used for encrypting gossip between the agents 6 // which is used to exchange service discovery and overlay network control 7 // plane information. It can also be used to encrypt overlay data traffic. 8 import ( 9 "context" 10 cryptorand "crypto/rand" 11 "encoding/binary" 12 "sync" 13 "time" 14 15 "github.com/docker/swarmkit/api" 16 "github.com/docker/swarmkit/log" 17 "github.com/docker/swarmkit/manager/state/store" 18 "github.com/pkg/errors" 19 ) 20 21 const ( 22 // DefaultKeyLen is the default length (in bytes) of the key allocated 23 DefaultKeyLen = 16 24 25 // DefaultKeyRotationInterval used by key manager 26 DefaultKeyRotationInterval = 12 * time.Hour 27 28 // SubsystemGossip handles gossip protocol between the agents 29 SubsystemGossip = "networking:gossip" 30 31 // SubsystemIPSec is overlay network data encryption subsystem 32 SubsystemIPSec = "networking:ipsec" 33 34 // DefaultSubsystem is gossip 35 DefaultSubsystem = SubsystemGossip 36 // number of keys to mainrain in the key ring. 37 keyringSize = 3 38 ) 39 40 // map of subsystems and corresponding encryption algorithm. Initially only 41 // AES_128 in GCM mode is supported. 42 var subsysToAlgo = map[string]api.EncryptionKey_Algorithm{ 43 SubsystemGossip: api.AES_128_GCM, 44 SubsystemIPSec: api.AES_128_GCM, 45 } 46 47 type keyRing struct { 48 lClock uint64 49 keys []*api.EncryptionKey 50 } 51 52 // Config for the keymanager that can be modified 53 type Config struct { 54 ClusterName string 55 Keylen int 56 RotationInterval time.Duration 57 Subsystems []string 58 } 59 60 // KeyManager handles key allocation, rotation & distribution 61 type KeyManager struct { 62 config *Config 63 store *store.MemoryStore 64 keyRing *keyRing 65 ctx context.Context 66 cancel context.CancelFunc 67 68 mu sync.Mutex 69 } 70 71 // DefaultConfig provides the default config for keymanager 72 func DefaultConfig() *Config { 73 return &Config{ 74 ClusterName: store.DefaultClusterName, 75 Keylen: DefaultKeyLen, 76 RotationInterval: DefaultKeyRotationInterval, 77 Subsystems: []string{SubsystemGossip, SubsystemIPSec}, 78 } 79 } 80 81 // New creates an instance of keymanager with the given config 82 func New(store *store.MemoryStore, config *Config) *KeyManager { 83 for _, subsys := range config.Subsystems { 84 if subsys != SubsystemGossip && subsys != SubsystemIPSec { 85 return nil 86 } 87 } 88 return &KeyManager{ 89 config: config, 90 store: store, 91 keyRing: &keyRing{lClock: genSkew()}, 92 } 93 } 94 95 func (k *KeyManager) allocateKey(ctx context.Context, subsys string) *api.EncryptionKey { 96 key := make([]byte, k.config.Keylen) 97 98 _, err := cryptorand.Read(key) 99 if err != nil { 100 panic(errors.Wrap(err, "key generated failed")) 101 } 102 k.keyRing.lClock++ 103 104 return &api.EncryptionKey{ 105 Subsystem: subsys, 106 Algorithm: subsysToAlgo[subsys], 107 Key: key, 108 LamportTime: k.keyRing.lClock, 109 } 110 } 111 112 func (k *KeyManager) updateKey(cluster *api.Cluster) error { 113 return k.store.Update(func(tx store.Tx) error { 114 cluster = store.GetCluster(tx, cluster.ID) 115 if cluster == nil { 116 return nil 117 } 118 cluster.EncryptionKeyLamportClock = k.keyRing.lClock 119 cluster.NetworkBootstrapKeys = k.keyRing.keys 120 return store.UpdateCluster(tx, cluster) 121 }) 122 } 123 124 func (k *KeyManager) rotateKey(ctx context.Context) error { 125 var ( 126 clusters []*api.Cluster 127 err error 128 ) 129 k.store.View(func(readTx store.ReadTx) { 130 clusters, err = store.FindClusters(readTx, store.ByName(k.config.ClusterName)) 131 }) 132 133 if err != nil { 134 log.G(ctx).Errorf("reading cluster config failed, %v", err) 135 return err 136 } 137 138 cluster := clusters[0] 139 if len(cluster.NetworkBootstrapKeys) == 0 { 140 panic(errors.New("no key in the cluster config")) 141 } 142 143 subsysKeys := map[string][]*api.EncryptionKey{} 144 for _, key := range k.keyRing.keys { 145 subsysKeys[key.Subsystem] = append(subsysKeys[key.Subsystem], key) 146 } 147 k.keyRing.keys = []*api.EncryptionKey{} 148 149 // We maintain the latest key and the one before in the key ring to allow 150 // agents to communicate without disruption on key change. 151 for subsys, keys := range subsysKeys { 152 if len(keys) == keyringSize { 153 min := 0 154 for i, key := range keys[1:] { 155 if key.LamportTime < keys[min].LamportTime { 156 min = i 157 } 158 } 159 keys = append(keys[0:min], keys[min+1:]...) 160 } 161 keys = append(keys, k.allocateKey(ctx, subsys)) 162 subsysKeys[subsys] = keys 163 } 164 165 for _, keys := range subsysKeys { 166 k.keyRing.keys = append(k.keyRing.keys, keys...) 167 } 168 169 return k.updateKey(cluster) 170 } 171 172 // Run starts the keymanager, it doesn't return 173 func (k *KeyManager) Run(ctx context.Context) error { 174 k.mu.Lock() 175 ctx = log.WithModule(ctx, "keymanager") 176 var ( 177 clusters []*api.Cluster 178 err error 179 ) 180 k.store.View(func(readTx store.ReadTx) { 181 clusters, err = store.FindClusters(readTx, store.ByName(k.config.ClusterName)) 182 }) 183 184 if err != nil { 185 log.G(ctx).Errorf("reading cluster config failed, %v", err) 186 k.mu.Unlock() 187 return err 188 } 189 190 cluster := clusters[0] 191 if len(cluster.NetworkBootstrapKeys) == 0 { 192 for _, subsys := range k.config.Subsystems { 193 for i := 0; i < keyringSize; i++ { 194 k.keyRing.keys = append(k.keyRing.keys, k.allocateKey(ctx, subsys)) 195 } 196 } 197 if err := k.updateKey(cluster); err != nil { 198 log.G(ctx).Errorf("store update failed %v", err) 199 } 200 } else { 201 k.keyRing.lClock = cluster.EncryptionKeyLamportClock 202 k.keyRing.keys = cluster.NetworkBootstrapKeys 203 } 204 205 ticker := time.NewTicker(k.config.RotationInterval) 206 defer ticker.Stop() 207 208 k.ctx, k.cancel = context.WithCancel(ctx) 209 k.mu.Unlock() 210 211 for { 212 select { 213 case <-ticker.C: 214 k.rotateKey(ctx) 215 case <-k.ctx.Done(): 216 return nil 217 } 218 } 219 } 220 221 // Stop stops the running instance of key manager 222 func (k *KeyManager) Stop() error { 223 k.mu.Lock() 224 defer k.mu.Unlock() 225 if k.cancel == nil { 226 return errors.New("keymanager is not started") 227 } 228 k.cancel() 229 return nil 230 } 231 232 // genSkew generates a random uint64 number between 0 and 65535 233 func genSkew() uint64 { 234 b := make([]byte, 2) 235 if _, err := cryptorand.Read(b); err != nil { 236 panic(err) 237 } 238 return uint64(binary.BigEndian.Uint16(b)) 239 }