Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / docker / swarmkit / manager / keymanager / keymanager.go
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         cryptorand "crypto/rand"
10         "encoding/binary"
11         "sync"
12         "time"
13
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"
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 }