Skip to content
Snippets Groups Projects
Commit 101409cd authored by Fabian Seidl's avatar Fabian Seidl
Browse files

Resolve "Make interval, amount of keys to poll from qkd modules and max keys configurable"

See merge request !180
parent 0d951592
No related branches found
No related tags found
1 merge request!180Resolve "Make interval, amount of keys to poll from qkd modules and max keys configurable"
Pipeline #219541 passed
...@@ -89,6 +89,9 @@ Peers: ...@@ -89,6 +89,9 @@ Peers:
Mastermode: true # (Type: etsi specific) Sets the QuantumModule in MasterMode. Keys are requested via GetKey and synced with peer KMS. Mastermode: true # (Type: etsi specific) Sets the QuantumModule in MasterMode. Keys are requested via GetKey and synced with peer KMS.
LocalSAEID: "localSAEID" # the related ID of the local SAE LocalSAEID: "localSAEID" # the related ID of the local SAE
TargetSAEID: "targetSAEID" # the related ID of the target SAE TargetSAEID: "targetSAEID" # the related ID of the target SAE
KeyFetchInterval: 10 # interval in seconds for how often keys should be requested from a QuantumModule (optional, uses default if not provided)
KeyFetchAmount: 10 # amount of keys to be requested from a QuantumModule (optional, uses default if not provided)
MaxKeyFillLevel: 100 # maximum number of keys to be stored in the storage related to one KMS peer (should be the same for the peer on the other side, uses default if not provided)
# peer to goKMS03 # peer to goKMS03
- PeerId: "f80db2c0-2480-46b9-b7d1-b63f954e8227" - PeerId: "f80db2c0-2480-46b9-b7d1-b63f954e8227"
PeerInterComAddr: 172.100.20.12:50910 PeerInterComAddr: 172.100.20.12:50910
......
...@@ -34,12 +34,15 @@ type TLSConfig struct { ...@@ -34,12 +34,15 @@ type TLSConfig struct {
} }
type QuantumModule struct { type QuantumModule struct {
QmType string `yaml:"Type"` QmType string `yaml:"Type"`
Address string `yaml:"Address"` Address string `yaml:"Address"`
Hostname string `yaml:"Hostname"` Hostname string `yaml:"Hostname"`
LocalSAEID string `yaml:"LocalSAEID"` LocalSAEID string `yaml:"LocalSAEID"`
TargetSAEID string `yaml:"TargetSAEID"` TargetSAEID string `yaml:"TargetSAEID"`
MasterMode bool `yaml:"MasterMode"` MasterMode bool `yaml:"MasterMode"`
KeyFetchInterval int `yaml:"KeyFetchInterval"`
KeyFetchAmount int `yaml:"KeyFetchAmount"`
MaxKeyFillLevel int `yaml:"MaxKeyFillLevel"`
} }
type ETSI14Server struct { type ETSI14Server struct {
......
package kmsHandler
import (
"fmt"
"code.fbi.h-da.de/danet/gnmi-target/handler"
"code.fbi.h-da.de/danet/quant/goKMS/kms"
"code.fbi.h-da.de/danet/quant/goKMS/kms/event"
gnmitargetygot "code.fbi.h-da.de/danet/quant/goKMS/model"
"github.com/openconfig/gnmi/proto/gnmi"
"github.com/openconfig/ygot/ygot"
"github.com/sirupsen/logrus"
)
type KeyStoreHandler struct {
handler.DefaultPathHandler
kms *kms.KMS
maxKeyFillLevelsDefined map[string]uint64
events <-chan event.Event
}
type keyFillLevel struct {
storeID string
fillLevel uint64
}
func NewKeyStoreHandler(kms *kms.KMS, maxKeyFillLevelsDefined map[string]uint64) *KeyStoreHandler {
return &KeyStoreHandler{
DefaultPathHandler: handler.DefaultPathHandler{
Name: "key-store-handler",
Paths: map[string]struct{}{
"key-stores": {},
},
},
kms: kms,
maxKeyFillLevelsDefined: maxKeyFillLevelsDefined,
}
}
func (yh *KeyStoreHandler) Init(config *handler.Config, publishToSubsFunc func([]*gnmi.Notification) error) error {
yh.Config = config
yh.PublishToSubs = publishToSubsFunc
var err error
yh.events, err = yh.kms.EventBus().Subscribe(event.KEY_STORE)
if err != nil {
return err
}
_, err = yh.updateOrCreateKeyStoreHandler()
if err != nil {
return err
}
// Start the go routine that takes care of any update from the kms
go func() {
for {
select {
case <-yh.events:
logrus.Println("Update for KeyStores.")
_, err := yh.updateOrCreateKeyStoreHandler()
if err != nil {
logrus.Errorf("Error within key stores subscription goroutine; %v", err)
}
// gnmi subscribe things here?
}
}
}()
return nil
}
func (yh *KeyStoreHandler) Update(c ygot.ValidatedGoStruct, jobs []*gnmi.Update) error {
return nil
}
func (yh *KeyStoreHandler) updateOrCreateKeyStoreHandler() ([]*gnmi.Notification, error) {
yh.Config.Lock()
defer yh.Config.Unlock()
copyCurrentConfig, err := ygot.DeepCopy(yh.Config.Data)
if err != nil {
return nil, err
}
newConfig, ok := copyCurrentConfig.(*gnmitargetygot.Gnmitarget)
if !ok {
return nil, fmt.Errorf("Wrong type, exptected: %T, got: %T", (*gnmitargetygot.Temp_KeyStores)(nil), copyCurrentConfig)
}
confKeyStores := newConfig.GetOrCreateKeyStores()
keyFillLevels := getKeyFillLevels(yh.kms)
// TODO: Maybe add more config values here!
for _, keyFillLevel := range keyFillLevels {
confKeyStoreContainer := confKeyStores.GetOrCreateKeyStore(keyFillLevel.storeID)
confKeyStoreContainer.KmsPeerId = ygot.String(keyFillLevel.storeID)
confKeyStore := confKeyStoreContainer.GetOrCreateKeyStore()
confKeyStore.KeyFillLevel = ygot.Uint64(keyFillLevel.fillLevel)
maxKeyFillLevel, ok := yh.maxKeyFillLevelsDefined[keyFillLevel.storeID]
if !ok {
return nil, fmt.Errorf("no max key fill level available for store with ID: %s", keyFillLevel.storeID) // TODO(faseid): check if really want to return here?!
}
confKeyStore.MaxKeyFillLevel = ygot.Uint64(maxKeyFillLevel)
}
// validate struct
if err := newConfig.Validate(); err != nil {
return nil, err
}
notifications, err := ygot.DiffWithAtomic(yh.Config.Data, newConfig)
if err != nil {
return nil, err
}
yh.Config.Data = newConfig
return notifications, nil
}
func getKeyFillLevels(kms *kms.KMS) []keyFillLevel {
kmsPeers := kms.KmsPeers
keyFillLevels := []keyFillLevel{}
for _, peer := range kmsPeers {
keyFillLevels = append(keyFillLevels, keyFillLevel{
storeID: peer.GetKmsPeerId().String(),
fillLevel: uint64(peer.GetKeyStore().Length()),
})
}
return keyFillLevels
}
...@@ -9,6 +9,7 @@ const ( ...@@ -9,6 +9,7 @@ const (
ROUTE ROUTE
QUANTUM_MODULE QUANTUM_MODULE
CREATE_ROUTE CREATE_ROUTE
KEY_STORE
) )
// Event ... // Event ...
...@@ -86,3 +87,23 @@ func (e *RouteEvent) Topic() Topic { ...@@ -86,3 +87,23 @@ func (e *RouteEvent) Topic() Topic {
func (e *RouteEvent) Time() time.Time { func (e *RouteEvent) Time() time.Time {
return e.Timestamp return e.Timestamp
} }
type KeyStoresEvent struct {
EventTopic Topic
Timestamp time.Time
}
func NewKeyStoresEvent() *KeyStoresEvent {
return &KeyStoresEvent{
EventTopic: KEY_STORE,
Timestamp: time.Now(),
}
}
func (e *KeyStoresEvent) Topic() Topic {
return e.EventTopic
}
func (e *KeyStoresEvent) Time() time.Time {
return e.Timestamp
}
...@@ -190,7 +190,10 @@ func (kms *KMS) initializePeers(config *config.Config) error { ...@@ -190,7 +190,10 @@ func (kms *KMS) initializePeers(config *config.Config) error {
case "emulated": case "emulated":
qm = peers.NewDanetQuantumModule(pqm.Address, config.Id) qm = peers.NewDanetQuantumModule(pqm.Address, config.Id)
case "etsi": case "etsi":
qm, err = peers.NewETSI014HTTPQuantumModule(pqm.Address, config.Id, pqm.LocalSAEID, pqm.TargetSAEID, config.QuantumModuleTLS, pqm.MasterMode) qm, err = peers.NewETSI014HTTPQuantumModule(pqm.Address, config.Id, pqm.LocalSAEID, pqm.TargetSAEID,
config.QuantumModuleTLS, pqm.MasterMode,
peer.QuantumModule.KeyFetchInterval, int64(peer.QuantumModule.KeyFetchAmount), uint64(peer.QuantumModule.MaxKeyFillLevel),
kms.eventBus)
if err != nil { if err != nil {
log.Fatalf("Failed to create ETSI QKD module: %s", err) log.Fatalf("Failed to create ETSI QKD module: %s", err)
return nil return nil
......
...@@ -18,19 +18,32 @@ import ( ...@@ -18,19 +18,32 @@ import (
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
) )
const (
maxFailedKeyRequestAttempts = 10
defaultKeyFetchInterval = 10
defaultKeyFetchAmount = int64(1)
defualtMaxKeyFillLevel = uint64(100)
backgroundKeyStoreUpdateInterval = 1
)
type ETSI014HTTPQuantumModule struct { type ETSI014HTTPQuantumModule struct {
id uuid.UUID id uuid.UUID
kmsId string kmsId string
addr string addr string
keyStore *store.KmsKeyStore keyStore *store.KmsKeyStore
kmsClient *GRPCClient kmsClient *GRPCClient
client *etsi14ClientImpl.ClientImpl client *etsi14ClientImpl.ClientImpl
localSAEID string localSAEID string
targetSAEID string targetSAEID string
master bool master bool
keyFetchInterval int
keyFetchAmount int64
maxKeyFillLevel uint64
kmsEventBus *event.EventBus
} }
func NewETSI014HTTPQuantumModule(addr, kmsId, localSAEID, targetSAEID string, tlsConfig config.TLSConfig, master bool) (*ETSI014HTTPQuantumModule, error) { func NewETSI014HTTPQuantumModule(addr, kmsId, localSAEID, targetSAEID string, tlsConfig config.TLSConfig, master bool, keyFetchInterval int, keyFetchAmount int64, maxKeyFillLevel uint64, kmsEventBus *event.EventBus) (*ETSI014HTTPQuantumModule, error) {
parsedUrl, err := url.Parse(addr) parsedUrl, err := url.Parse(addr)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -65,16 +78,33 @@ func NewETSI014HTTPQuantumModule(addr, kmsId, localSAEID, targetSAEID string, tl ...@@ -65,16 +78,33 @@ func NewETSI014HTTPQuantumModule(addr, kmsId, localSAEID, targetSAEID string, tl
return nil, err return nil, err
} }
// set defaults for key fetching if not defined in config
if keyFetchInterval == 0 {
keyFetchInterval = defaultKeyFetchInterval
}
if keyFetchAmount == 0 {
keyFetchAmount = defaultKeyFetchAmount
}
if maxKeyFillLevel == 0 {
maxKeyFillLevel = defualtMaxKeyFillLevel
}
return &ETSI014HTTPQuantumModule{ return &ETSI014HTTPQuantumModule{
id: uuid.New(), id: uuid.New(),
kmsId: kmsId, kmsId: kmsId,
addr: addr, addr: addr,
keyStore: store.NewKmsKeyStore(256), keyStore: store.NewKmsKeyStore(256),
kmsClient: nil, kmsClient: nil,
client: client, client: client,
localSAEID: localSAEID, localSAEID: localSAEID,
targetSAEID: targetSAEID, targetSAEID: targetSAEID,
master: master, master: master,
keyFetchInterval: keyFetchInterval,
keyFetchAmount: keyFetchAmount,
maxKeyFillLevel: maxKeyFillLevel,
kmsEventBus: kmsEventBus,
}, nil }, nil
} }
...@@ -87,38 +117,54 @@ func (qm *ETSI014HTTPQuantumModule) Client() *etsi14ClientImpl.ClientImpl { ...@@ -87,38 +117,54 @@ func (qm *ETSI014HTTPQuantumModule) Client() *etsi14ClientImpl.ClientImpl {
} }
func (qm *ETSI014HTTPQuantumModule) Initialize() error { func (qm *ETSI014HTTPQuantumModule) Initialize() error {
// start polling // sends events on the event bus every x seconds to keep key store config updated
go qm.runBackgroundKeyStoreUpdates()
// start polling keys
if qm.master { if qm.master {
go func() { go func() {
ticker := time.NewTicker(2 * time.Second) ticker := time.NewTicker(time.Duration(qm.keyFetchInterval) * time.Second)
defer ticker.Stop() defer ticker.Stop()
failedAttemps := 0
// TODO: add context/channel to stop // TODO: add context/channel to stop
for range ticker.C { for range ticker.C {
container, err := qm.GetKeys(1, 256, nil, nil, nil) if failedAttemps == maxFailedKeyRequestAttempts {
if err != nil { log.Errorf("stopped trying to fetch keys from qkd module after %d tries", failedAttemps)
log.Error(err)
break break
} }
keyIds := make([]string, len(container.GetKeys())) if qm.keyStore.Length() < int(qm.maxKeyFillLevel) {
for i, keyItem := range container.GetKeys() { container, err := qm.GetKeys(qm.keyFetchAmount, 256, nil, nil, nil)
keyIds[i] = keyItem.GetKeyID() if err != nil {
} log.Error(err)
failedAttemps++
_, err = qm.kmsClient.KeyIdNotification(context.Background(), continue
&pbIC.KeyIdNotificationRequest{ }
Timestamp: time.Now().Unix(),
KmsId: qm.kmsId, keyIds := make([]string, len(container.GetKeys()))
KeyIds: keyIds, for i, keyItem := range container.GetKeys() {
}) keyIds[i] = keyItem.GetKeyID()
if err != nil { }
log.Error(err)
break _, err = qm.kmsClient.KeyIdNotification(context.Background(),
} &pbIC.KeyIdNotificationRequest{
Timestamp: time.Now().Unix(),
if err := store.AddETSIKeysToKeystore(qm.keyStore, container.GetKeys()); err != nil { KmsId: qm.kmsId,
log.Error(err) KeyIds: keyIds,
})
if err != nil {
log.Error(err)
failedAttemps++
continue
}
if err := store.AddETSIKeysToKeystore(qm.keyStore, container.GetKeys()); err != nil {
log.Error(err)
}
failedAttemps = 0
} }
} }
}() }()
...@@ -179,3 +225,15 @@ func (qm *ETSI014HTTPQuantumModule) GetKeyWithIds(keyIds []etsi14ClientGenerated ...@@ -179,3 +225,15 @@ func (qm *ETSI014HTTPQuantumModule) GetKeyWithIds(keyIds []etsi14ClientGenerated
return container, nil return container, nil
} }
func (qm *ETSI014HTTPQuantumModule) runBackgroundKeyStoreUpdates() {
ticker := time.NewTicker(backgroundKeyStoreUpdateInterval * time.Second)
defer ticker.Stop()
for range ticker.C {
err := qm.kmsEventBus.Publish(event.NewKeyStoresEvent())
if err != nil {
log.Error(err)
}
}
}
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
pbIC "code.fbi.h-da.de/danet/quant/goKMS/api/gen/proto/go/kmsintercom" pbIC "code.fbi.h-da.de/danet/quant/goKMS/api/gen/proto/go/kmsintercom"
"code.fbi.h-da.de/danet/quant/goKMS/kms/crypto" "code.fbi.h-da.de/danet/quant/goKMS/kms/crypto"
"code.fbi.h-da.de/danet/quant/goKMS/kms/event" "code.fbi.h-da.de/danet/quant/goKMS/kms/event"
"code.fbi.h-da.de/danet/quant/goKMS/kms/store"
"code.fbi.h-da.de/danet/quant/goKMS/kms/util" "code.fbi.h-da.de/danet/quant/goKMS/kms/util"
"github.com/google/uuid" "github.com/google/uuid"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
...@@ -214,3 +215,7 @@ func (kp *KmsPeer) SetStatus(updateStatus KmsPeerStatus) { ...@@ -214,3 +215,7 @@ func (kp *KmsPeer) SetStatus(updateStatus KmsPeerStatus) {
func (kp *KmsPeer) GetKmsPeerId() uuid.UUID { func (kp *KmsPeer) GetKmsPeerId() uuid.UUID {
return kp.peerKmsId return kp.peerKmsId
} }
func (kp *KmsPeer) GetKeyStore() *store.KmsKeyStore {
return kp.servingQuantumModul.KeyStore()
}
...@@ -124,6 +124,8 @@ func main() { ...@@ -124,6 +124,8 @@ func main() {
log.Fatal(err) log.Fatal(err)
} }
maxKeyFillLevels := getMaxKeyFillLevelsFromConfig(kmsConfig.Peers)
// The registered path handlers sorted by priority. If specific // The registered path handlers sorted by priority. If specific
// handlers should be able to process their workload before others, // handlers should be able to process their workload before others,
// then they should be placed in the front of the slice. // then they should be placed in the front of the slice.
...@@ -137,6 +139,7 @@ func main() { ...@@ -137,6 +139,7 @@ func main() {
kmsHandler.NewPeerHandler(kms), kmsHandler.NewPeerHandler(kms),
kmsHandler.NewKeyRoutingSessionHandler(kms), kmsHandler.NewKeyRoutingSessionHandler(kms),
kmsHandler.NewAssignForwardingHandler(kms), kmsHandler.NewAssignForwardingHandler(kms),
kmsHandler.NewKeyStoreHandler(kms, maxKeyFillLevels),
} }
// The gnmiTarget implementation uses a flag to pass NO tls, so we have to invert our flag for it to work. // The gnmiTarget implementation uses a flag to pass NO tls, so we have to invert our flag for it to work.
...@@ -233,3 +236,13 @@ func setupQkdnManagerServer(kms *kms.KMS, config config.QkdnManagerServer) { ...@@ -233,3 +236,13 @@ func setupQkdnManagerServer(kms *kms.KMS, config config.QkdnManagerServer) {
cancel() cancel()
} }
func getMaxKeyFillLevelsFromConfig(peers []config.Peer) map[string]uint64 {
maxKeyFillLevels := make(map[string]uint64, 0)
for _, peer := range peers {
maxKeyFillLevels[peer.PeerId] = uint64(peer.QuantumModule.MaxKeyFillLevel)
}
return maxKeyFillLevels
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment