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.
9 cryptorand "crypto/rand"
14 "github.com/docker/swarmkit/api"
15 "github.com/docker/swarmkit/log"
16 "github.com/docker/swarmkit/manager/state/store"
17 "github.com/pkg/errors"
18 "golang.org/x/net/context"
22 // DefaultKeyLen is the default length (in bytes) of the key allocated
25 // DefaultKeyRotationInterval used by key manager
26 DefaultKeyRotationInterval = 12 * time.Hour
28 // SubsystemGossip handles gossip protocol between the agents
29 SubsystemGossip = "networking:gossip"
31 // SubsystemIPSec is overlay network data encryption subsystem
32 SubsystemIPSec = "networking:ipsec"
34 // DefaultSubsystem is gossip
35 DefaultSubsystem = SubsystemGossip
36 // number of keys to mainrain in the key ring.
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,
49 keys []*api.EncryptionKey
52 // Config for the keymanager that can be modified
56 RotationInterval time.Duration
60 // KeyManager handles key allocation, rotation & distribution
61 type KeyManager struct {
63 store *store.MemoryStore
66 cancel context.CancelFunc
71 // DefaultConfig provides the default config for keymanager
72 func DefaultConfig() *Config {
74 ClusterName: store.DefaultClusterName,
75 Keylen: DefaultKeyLen,
76 RotationInterval: DefaultKeyRotationInterval,
77 Subsystems: []string{SubsystemGossip, SubsystemIPSec},
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 {
91 keyRing: &keyRing{lClock: genSkew()},
95 func (k *KeyManager) allocateKey(ctx context.Context, subsys string) *api.EncryptionKey {
96 key := make([]byte, k.config.Keylen)
98 _, err := cryptorand.Read(key)
100 panic(errors.Wrap(err, "key generated failed"))
104 return &api.EncryptionKey{
106 Algorithm: subsysToAlgo[subsys],
108 LamportTime: k.keyRing.lClock,
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)
118 cluster.EncryptionKeyLamportClock = k.keyRing.lClock
119 cluster.NetworkBootstrapKeys = k.keyRing.keys
120 return store.UpdateCluster(tx, cluster)
124 func (k *KeyManager) rotateKey(ctx context.Context) error {
126 clusters []*api.Cluster
129 k.store.View(func(readTx store.ReadTx) {
130 clusters, err = store.FindClusters(readTx, store.ByName(k.config.ClusterName))
134 log.G(ctx).Errorf("reading cluster config failed, %v", err)
138 cluster := clusters[0]
139 if len(cluster.NetworkBootstrapKeys) == 0 {
140 panic(errors.New("no key in the cluster config"))
143 subsysKeys := map[string][]*api.EncryptionKey{}
144 for _, key := range k.keyRing.keys {
145 subsysKeys[key.Subsystem] = append(subsysKeys[key.Subsystem], key)
147 k.keyRing.keys = []*api.EncryptionKey{}
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 {
154 for i, key := range keys[1:] {
155 if key.LamportTime < keys[min].LamportTime {
159 keys = append(keys[0:min], keys[min+1:]...)
161 keys = append(keys, k.allocateKey(ctx, subsys))
162 subsysKeys[subsys] = keys
165 for _, keys := range subsysKeys {
166 k.keyRing.keys = append(k.keyRing.keys, keys...)
169 return k.updateKey(cluster)
172 // Run starts the keymanager, it doesn't return
173 func (k *KeyManager) Run(ctx context.Context) error {
175 ctx = log.WithModule(ctx, "keymanager")
177 clusters []*api.Cluster
180 k.store.View(func(readTx store.ReadTx) {
181 clusters, err = store.FindClusters(readTx, store.ByName(k.config.ClusterName))
185 log.G(ctx).Errorf("reading cluster config failed, %v", err)
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))
197 if err := k.updateKey(cluster); err != nil {
198 log.G(ctx).Errorf("store update failed %v", err)
201 k.keyRing.lClock = cluster.EncryptionKeyLamportClock
202 k.keyRing.keys = cluster.NetworkBootstrapKeys
205 ticker := time.NewTicker(k.config.RotationInterval)
208 k.ctx, k.cancel = context.WithCancel(ctx)
221 // Stop stops the running instance of key manager
222 func (k *KeyManager) Stop() error {
226 return errors.New("keymanager is not started")
232 // genSkew generates a random uint64 number between 0 and 65535
233 func genSkew() uint64 {
235 if _, err := cryptorand.Read(b); err != nil {
238 return uint64(binary.BigEndian.Uint16(b))