mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Merge pull request #1275 from sanimej/3keys
Update key handling logic to process keyring with 3 keys
This commit is contained in:
commit
090a12035f
5 changed files with 170 additions and 75 deletions
|
@ -3,12 +3,10 @@ package libnetwork
|
|||
//go:generate protoc -I.:Godeps/_workspace/src/github.com/gogo/protobuf --gogo_out=import_path=github.com/docker/libnetwork,Mgogoproto/gogo.proto=github.com/gogo/protobuf/gogoproto:. agent.proto
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"github.com/Sirupsen/logrus"
|
||||
"github.com/docker/go-events"
|
||||
|
@ -20,6 +18,12 @@ import (
|
|||
"github.com/gogo/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
subsysGossip = "networking:gossip"
|
||||
subsysIPSec = "networking:ipsec"
|
||||
keyringSize = 3
|
||||
)
|
||||
|
||||
// ByTime implements sort.Interface for []*types.EncryptionKey based on
|
||||
// the LamportTime field.
|
||||
type ByTime []*types.EncryptionKey
|
||||
|
@ -80,6 +84,82 @@ func resolveAddr(addrOrInterface string) (string, error) {
|
|||
func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error {
|
||||
drvEnc := discoverapi.DriverEncryptionUpdate{}
|
||||
|
||||
a := c.agent
|
||||
// Find the deleted key. If the deleted key was the primary key,
|
||||
// a new primary key should be set before removing if from keyring.
|
||||
deleted := []byte{}
|
||||
j := len(c.keys)
|
||||
for i := 0; i < j; {
|
||||
same := false
|
||||
for _, key := range keys {
|
||||
if same = key.LamportTime == c.keys[i].LamportTime; same {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !same {
|
||||
cKey := c.keys[i]
|
||||
if cKey.Subsystem == subsysGossip {
|
||||
deleted = cKey.Key
|
||||
}
|
||||
|
||||
if cKey.Subsystem == subsysGossip /* subsysIPSec */ {
|
||||
drvEnc.Prune = cKey.Key
|
||||
drvEnc.PruneTag = cKey.LamportTime
|
||||
}
|
||||
c.keys[i], c.keys[j-1] = c.keys[j-1], c.keys[i]
|
||||
c.keys[j-1] = nil
|
||||
j--
|
||||
}
|
||||
i++
|
||||
}
|
||||
c.keys = c.keys[:j]
|
||||
|
||||
// Find the new key and add it to the key ring
|
||||
for _, key := range keys {
|
||||
same := false
|
||||
for _, cKey := range c.keys {
|
||||
if same = cKey.LamportTime == key.LamportTime; same {
|
||||
break
|
||||
}
|
||||
}
|
||||
if !same {
|
||||
c.keys = append(c.keys, key)
|
||||
if key.Subsystem == subsysGossip {
|
||||
a.networkDB.SetKey(key.Key)
|
||||
}
|
||||
|
||||
if key.Subsystem == subsysGossip /*subsysIPSec*/ {
|
||||
drvEnc.Key = key.Key
|
||||
drvEnc.Tag = key.LamportTime
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
key, tag := c.getPrimaryKeyTag(subsysGossip)
|
||||
a.networkDB.SetPrimaryKey(key)
|
||||
|
||||
//key, tag = c.getPrimaryKeyTag(subsysIPSec)
|
||||
drvEnc.Primary = key
|
||||
drvEnc.PrimaryTag = tag
|
||||
|
||||
if len(deleted) > 0 {
|
||||
a.networkDB.RemoveKey(deleted)
|
||||
}
|
||||
|
||||
c.drvRegistry.WalkDrivers(func(name string, driver driverapi.Driver, capability driverapi.Capability) bool {
|
||||
err := driver.DiscoverNew(discoverapi.EncryptionKeysUpdate, drvEnc)
|
||||
if err != nil {
|
||||
logrus.Warnf("Failed to update datapath keys in driver %s: %v", name, err)
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *controller) handleKeyChangeV1(keys []*types.EncryptionKey) error {
|
||||
drvEnc := discoverapi.DriverEncryptionUpdate{}
|
||||
|
||||
// Find the new key and add it to the key ring
|
||||
a := c.agent
|
||||
for _, key := range keys {
|
||||
|
@ -91,12 +171,12 @@ func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error {
|
|||
}
|
||||
if !same {
|
||||
c.keys = append(c.keys, key)
|
||||
if key.Subsystem == "networking:gossip" {
|
||||
if key.Subsystem == subsysGossip {
|
||||
a.networkDB.SetKey(key.Key)
|
||||
}
|
||||
if key.Subsystem == "networking:gossip" /*"networking:ipsec"*/ {
|
||||
drvEnc.Key = hex.EncodeToString(key.Key)
|
||||
drvEnc.Tag = strconv.FormatUint(key.LamportTime, 10)
|
||||
if key.Subsystem == subsysGossip /*subsysIPSec*/ {
|
||||
drvEnc.Key = key.Key
|
||||
drvEnc.Tag = key.LamportTime
|
||||
}
|
||||
break
|
||||
}
|
||||
|
@ -112,12 +192,12 @@ func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error {
|
|||
}
|
||||
}
|
||||
if !same {
|
||||
if cKey.Subsystem == "networking:gossip" {
|
||||
if cKey.Subsystem == subsysGossip {
|
||||
deleted = cKey.Key
|
||||
}
|
||||
if cKey.Subsystem == "networking:gossip" /*"networking:ipsec"*/ {
|
||||
drvEnc.Prune = hex.EncodeToString(cKey.Key)
|
||||
drvEnc.PruneTag = strconv.FormatUint(cKey.LamportTime, 10)
|
||||
if cKey.Subsystem == subsysGossip /*subsysIPSec*/ {
|
||||
drvEnc.Prune = cKey.Key
|
||||
drvEnc.PruneTag = cKey.LamportTime
|
||||
}
|
||||
c.keys = append(c.keys[:i], c.keys[i+1:]...)
|
||||
break
|
||||
|
@ -126,15 +206,15 @@ func (c *controller) handleKeyChange(keys []*types.EncryptionKey) error {
|
|||
|
||||
sort.Sort(ByTime(c.keys))
|
||||
for _, key := range c.keys {
|
||||
if key.Subsystem == "networking:gossip" {
|
||||
if key.Subsystem == subsysGossip {
|
||||
a.networkDB.SetPrimaryKey(key.Key)
|
||||
break
|
||||
}
|
||||
}
|
||||
for _, key := range c.keys {
|
||||
if key.Subsystem == "networking:gossip" /*"networking:ipsec"*/ {
|
||||
drvEnc.Primary = hex.EncodeToString(key.Key)
|
||||
drvEnc.PrimaryTag = strconv.FormatUint(key.LamportTime, 10)
|
||||
if key.Subsystem == subsysGossip /*subsysIPSec*/ {
|
||||
drvEnc.Primary = key.Key
|
||||
drvEnc.PrimaryTag = key.LamportTime
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -197,6 +277,41 @@ func (c *controller) agentSetup() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// For a given subsystem getKeys sorts the keys by lamport time and returns
|
||||
// slice of keys and lamport time which can used as a unique tag for the keys
|
||||
func (c *controller) getKeys(subsys string) ([][]byte, []uint64) {
|
||||
sort.Sort(ByTime(c.keys))
|
||||
|
||||
keys := [][]byte{}
|
||||
tags := []uint64{}
|
||||
for _, key := range c.keys {
|
||||
if key.Subsystem == subsys {
|
||||
keys = append(keys, key.Key)
|
||||
tags = append(tags, key.LamportTime)
|
||||
}
|
||||
}
|
||||
|
||||
if len(keys) < keyringSize {
|
||||
return keys, tags
|
||||
}
|
||||
keys[0], keys[1] = keys[1], keys[0]
|
||||
tags[0], tags[1] = tags[1], tags[0]
|
||||
return keys, tags
|
||||
}
|
||||
|
||||
// getPrimaryKeyTag returns the primary key for a given subsytem from the
|
||||
// list of sorted key and the associated tag
|
||||
func (c *controller) getPrimaryKeyTag(subsys string) ([]byte, uint64) {
|
||||
sort.Sort(ByTime(c.keys))
|
||||
keys := []*types.EncryptionKey{}
|
||||
for _, key := range c.keys {
|
||||
if key.Subsystem == subsys {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
}
|
||||
return keys[1].Key, keys[1].LamportTime
|
||||
}
|
||||
|
||||
func (c *controller) agentInit(bindAddrOrInterface string) error {
|
||||
if !c.isAgent() {
|
||||
return nil
|
||||
|
@ -204,19 +319,9 @@ func (c *controller) agentInit(bindAddrOrInterface string) error {
|
|||
|
||||
drvEnc := discoverapi.DriverEncryptionConfig{}
|
||||
|
||||
// sort the keys by lamport time
|
||||
sort.Sort(ByTime(c.keys))
|
||||
|
||||
gossipkey := [][]byte{}
|
||||
for _, key := range c.keys {
|
||||
if key.Subsystem == "networking:gossip" {
|
||||
gossipkey = append(gossipkey, key.Key)
|
||||
}
|
||||
if key.Subsystem == "networking:gossip" /*"networking:ipsec"*/ {
|
||||
drvEnc.Keys = append(drvEnc.Keys, hex.EncodeToString(key.Key))
|
||||
drvEnc.Tags = append(drvEnc.Tags, strconv.FormatUint(key.LamportTime, 10))
|
||||
}
|
||||
}
|
||||
keys, tags := c.getKeys(subsysGossip) // getKeys(subsysIPSec)
|
||||
drvEnc.Keys = keys
|
||||
drvEnc.Tags = tags
|
||||
|
||||
bindAddr, err := resolveAddr(bindAddrOrInterface)
|
||||
if err != nil {
|
||||
|
@ -227,7 +332,7 @@ func (c *controller) agentInit(bindAddrOrInterface string) error {
|
|||
nDB, err := networkdb.New(&networkdb.Config{
|
||||
BindAddr: bindAddr,
|
||||
NodeName: hostname,
|
||||
Keys: gossipkey,
|
||||
Keys: keys,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
@ -275,12 +380,10 @@ func (c *controller) agentDriverNotify(d driverapi.Driver) {
|
|||
})
|
||||
|
||||
drvEnc := discoverapi.DriverEncryptionConfig{}
|
||||
for _, key := range c.keys {
|
||||
if key.Subsystem == "networking:gossip" /*"networking:ipsec"*/ {
|
||||
drvEnc.Keys = append(drvEnc.Keys, hex.EncodeToString(key.Key))
|
||||
drvEnc.Tags = append(drvEnc.Tags, strconv.FormatUint(key.LamportTime, 10))
|
||||
}
|
||||
}
|
||||
keys, tags := c.getKeys(subsysGossip) // getKeys(subsysIPSec)
|
||||
drvEnc.Keys = keys
|
||||
drvEnc.Tags = tags
|
||||
|
||||
c.drvRegistry.WalkDrivers(func(name string, driver driverapi.Driver, capability driverapi.Capability) bool {
|
||||
err := driver.DiscoverNew(discoverapi.EncryptionKeysConfig, drvEnc)
|
||||
if err != nil {
|
||||
|
|
|
@ -264,6 +264,9 @@ func (c *controller) SetKeys(keys []*types.EncryptionKey) error {
|
|||
c.Unlock()
|
||||
return nil
|
||||
}
|
||||
if len(keys) < keyringSize {
|
||||
return c.handleKeyChangeV1(keys)
|
||||
}
|
||||
return c.handleKeyChange(keys)
|
||||
}
|
||||
|
||||
|
|
|
@ -42,18 +42,18 @@ type DatastoreConfigData struct {
|
|||
// Key in first position is the primary key, the one to be used in tx.
|
||||
// Original key and tag types are []byte and uint64
|
||||
type DriverEncryptionConfig struct {
|
||||
Keys []string
|
||||
Tags []string
|
||||
Keys [][]byte
|
||||
Tags []uint64
|
||||
}
|
||||
|
||||
// DriverEncryptionUpdate carries an update to the encryption key(s) as:
|
||||
// a new key and/or set a primary key and/or a removal of an existing key.
|
||||
// Original key and tag types are []byte and uint64
|
||||
type DriverEncryptionUpdate struct {
|
||||
Key string
|
||||
Tag string
|
||||
Primary string
|
||||
PrimaryTag string
|
||||
Prune string
|
||||
PruneTag string
|
||||
Key []byte
|
||||
Tag uint64
|
||||
Primary []byte
|
||||
PrimaryTag uint64
|
||||
Prune []byte
|
||||
PruneTag uint64
|
||||
}
|
||||
|
|
|
@ -33,7 +33,10 @@ type key struct {
|
|||
}
|
||||
|
||||
func (k *key) String() string {
|
||||
return fmt.Sprintf("(key: %s, tag: 0x%x)", hex.EncodeToString(k.value)[0:5], k.tag)
|
||||
if k != nil {
|
||||
return fmt.Sprintf("(key: %s, tag: 0x%x)", hex.EncodeToString(k.value)[0:5], k.tag)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type spi struct {
|
||||
|
@ -557,23 +560,3 @@ func updateNodeKey(lIP, rIP net.IP, idxs []*spi, curKeys []*key, newIdx, priIdx,
|
|||
|
||||
return spis
|
||||
}
|
||||
|
||||
func parseEncryptionKey(value, tag string) (*key, error) {
|
||||
var (
|
||||
k *key
|
||||
err error
|
||||
)
|
||||
if value == "" {
|
||||
return nil, nil
|
||||
}
|
||||
k = &key{}
|
||||
if k.value, err = hex.DecodeString(value); err != nil {
|
||||
return nil, types.BadRequestErrorf("failed to decode key (%s): %v", value, err)
|
||||
}
|
||||
t, err := strconv.ParseUint(tag, 10, 64)
|
||||
if err != nil {
|
||||
return nil, types.BadRequestErrorf("failed to decode tag (%s): %v", tag, err)
|
||||
}
|
||||
k.tag = uint32(t)
|
||||
return k, nil
|
||||
}
|
||||
|
|
|
@ -306,9 +306,9 @@ func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{})
|
|||
}
|
||||
keys := make([]*key, 0, len(encrData.Keys))
|
||||
for i := 0; i < len(encrData.Keys); i++ {
|
||||
k, err := parseEncryptionKey(encrData.Keys[i], encrData.Tags[i])
|
||||
if err != nil {
|
||||
return err
|
||||
k := &key{
|
||||
value: encrData.Keys[i],
|
||||
tag: uint32(encrData.Tags[i]),
|
||||
}
|
||||
keys = append(keys, k)
|
||||
}
|
||||
|
@ -319,17 +319,23 @@ func (d *driver) DiscoverNew(dType discoverapi.DiscoveryType, data interface{})
|
|||
if !ok {
|
||||
return fmt.Errorf("invalid encryption key notification data")
|
||||
}
|
||||
newKey, err = parseEncryptionKey(encrData.Key, encrData.Tag)
|
||||
if err != nil {
|
||||
return err
|
||||
if encrData.Key != nil {
|
||||
newKey = &key{
|
||||
value: encrData.Key,
|
||||
tag: uint32(encrData.Tag),
|
||||
}
|
||||
}
|
||||
priKey, err = parseEncryptionKey(encrData.Primary, encrData.PrimaryTag)
|
||||
if err != nil {
|
||||
return err
|
||||
if encrData.Primary != nil {
|
||||
priKey = &key{
|
||||
value: encrData.Primary,
|
||||
tag: uint32(encrData.PrimaryTag),
|
||||
}
|
||||
}
|
||||
delKey, err = parseEncryptionKey(encrData.Prune, encrData.PruneTag)
|
||||
if err != nil {
|
||||
return err
|
||||
if encrData.Prune != nil {
|
||||
delKey = &key{
|
||||
value: encrData.Prune,
|
||||
tag: uint32(encrData.PruneTag),
|
||||
}
|
||||
}
|
||||
d.updateKeys(newKey, priKey, delKey)
|
||||
default:
|
||||
|
|
Loading…
Reference in a new issue