From d1604e5f3596c4d6851ec539a3fca47a811ca1f0 Mon Sep 17 00:00:00 2001
From: Malte Bauch <malte.bauch@h-da.de>
Date: Wed, 19 Feb 2025 14:15:54 +0100
Subject: [PATCH] Keystore extended with AddKeys method

---
 docker-compose.yml                        | 259 +++++++++++-----------
 goKMS/gnmiHandlers/kms/keyStoreHandler.go |  28 +--
 goKMS/kms/kmsintercom.go                  |   8 +-
 goKMS/kms/peers/danetQuantummodule.go     |   6 +-
 goKMS/kms/quipsec.go                      |  10 +-
 goKMS/kms/store/kms-keystore.go           |  40 +++-
 6 files changed, 183 insertions(+), 168 deletions(-)

diff --git a/docker-compose.yml b/docker-compose.yml
index 32355fb8..d1ca2a18 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -1,128 +1,133 @@
 services:
-  kms01:
-    image: gokms
-    command: ["--log", "debug", "--kms_config", "/tmp/kms/config/kms01.yaml"]
-    volumes:
-        - ./config/goKMS/example01.yaml:/tmp/kms/config/kms01.yaml
-        - ./artifacts/ssl:/ssl
-    ports:
-        - "127.0.0.1:4401:1337"
-        - "127.0.0.1:9696:9696"
-
-  kms02:
-    image: gokms
-    command: ["--log", "debug", "--kms_config", "/tmp/kms/config/kms02.yaml"]
-    volumes:
-        - ./config/goKMS/example02.yaml:/tmp/kms/config/kms02.yaml
-        - ./artifacts/ssl:/ssl
-    ports:
-        - "127.0.0.1:4402:1337"
-
-  kms03:
-    image: gokms
-    command: ["--log", "debug", "--kms_config", "/tmp/kms/config/kms03.yaml"]
-    volumes:
-        - ./config/goKMS/example03.yaml:/tmp/kms/config/kms03.yaml
-        - ./artifacts/ssl:/ssl
-    ports:
-        - "127.0.0.1:4403:1337"
-
-  kms04:
-    image: gokms
-    command: ["--log", "debug", "--kms_config", "/tmp/kms/config/kms04.yaml"]
-    volumes:
-        - ./config/goKMS/example04.yaml:/tmp/kms/config/kms04.yaml
-        - ./artifacts/ssl:/ssl
-    ports:
-        - "127.0.0.1:4404:1337"
-        - "127.0.0.1:9697:9696"
-
-  qlayer01:
-    image: quantumlayer
-    command: ["--config", "/tmp/quantumlayer/config/quantumlayer01.yaml"]
-    volumes:
-        - ./config/quantumlayer/example01.yaml:/tmp/quantumlayer/config/quantumlayer01.yaml
-
-  qlayer02:
-    image: quantumlayer
-    command: ["--config", "/tmp/quantumlayer/config/quantumlayer02.yaml"]
-    volumes:
-        - ./config/quantumlayer/example02.yaml:/tmp/quantumlayer/config/quantumlayer02.yaml
-
-  qlayer03:
-    image: quantumlayer
-    command: ["--config", "/tmp/quantumlayer/config/quantumlayer03.yaml"]
-    volumes:
-        - ./config/quantumlayer/example03.yaml:/tmp/quantumlayer/config/quantumlayer03.yaml
-
-  qlayer04:
-    image: quantumlayer
-    command: ["--config", "/tmp/quantumlayer/config/quantumlayer04.yaml"]
-    volumes:
-        - ./config/quantumlayer/example04.yaml:/tmp/quantumlayer/config/quantumlayer04.yaml
-
-  qlayer05:
-    image: quantumlayer
-    command: ["--config", "/tmp/quantumlayer/config/quantumlayer05.yaml"]
-    volumes:
-        - ./config/quantumlayer/example05.yaml:/tmp/quantumlayer/config/quantumlayer05.yaml
-
-  qlayer06:
-    image: quantumlayer
-    command: ["--config", "/tmp/quantumlayer/config/quantumlayer06.yaml"]
-    volumes:
-        - ./config/quantumlayer/example06.yaml:/tmp/quantumlayer/config/quantumlayer06.yaml
-
-  qlayer07:
-    image: quantumlayer
-    command: ["--config", "/tmp/quantumlayer/config/quantumlayer07.yaml"]
-    volumes:
-        - ./config/quantumlayer/example07.yaml:/tmp/quantumlayer/config/quantumlayer07.yaml
-
-  qlayer08:
-    image: quantumlayer
-    command: ["--config", "/tmp/quantumlayer/config/quantumlayer08.yaml"]
-    volumes:
-        - ./config/quantumlayer/example08.yaml:/tmp/quantumlayer/config/quantumlayer08.yaml
-
-  akms-receiver01:
-    image: akms-simulator
-
-  akms-receiver02:
-    image: akms-simulator
-
-  qkdn-controller:
-    image: registry.code.fbi.h-da.de/demoquandt/qkdn-controller:qkdn-main
-    volumes:
-      - ./config/controller/qkdn-gosdn.toml:/app/configs/qkdn-gosdn.toml
-      - ./config/controller/gNMISubscriptions.txt:/app/configs/gNMISubscriptions.txt
-    command: --config ./configs/qkdn-gosdn.toml
-    ports:
-      - "127.0.0.1:55055:55055"
-    environment:
-      GOSDN_ADMIN_PASSWORD: TestPassword
-
-  gosdnc:
-    image: registry.code.fbi.h-da.de/demoquandt/qkdn-controller/gosdnc:qkdn-main
-    volumes:
-      - ./config/controller/add_devices.sh:/scripts/add_devices.sh
-    entrypoint: ["/scripts/add_devices.sh"]
-
-  plugin-registry:
-    image: registry.code.fbi.h-da.de/demoquandt/qkdn-controller/plugin-registry:qkdn-main
-
-  mongo:
-    image: mongo:7
-    environment:
-      MONGO_INITDB_ROOT_USERNAME: root
-      MONGO_INITDB_ROOT_PASSWORD: example
-
-  rabbitmq:
-    image: rabbitmq:3-management
-
-  routing-app:
-    image: registry.code.fbi.h-da.de/demoquandt/qkdn-controller/routing-app:qkdn-main
-    entrypoint: ["./start_ra_sleep.sh"]
-    volumes:
-      - ./config/controller/start_ra_sleep.sh:/app/start_ra_sleep.sh
-      - ./config/controller/routing-config.yaml:/new/routing-config.yaml
+    kms01:
+        image: gokms
+        command:
+            ["--log", "debug", "--kms_config", "/tmp/kms/config/kms01.yaml"]
+        volumes:
+            - ./config/goKMS/example01.yaml:/tmp/kms/config/kms01.yaml
+            - ./artifacts/ssl:/ssl
+        ports:
+            - "127.0.0.1:7030:7030"
+            - "127.0.0.1:4401:1337"
+            - "127.0.0.1:9696:9696"
+
+    kms02:
+        image: gokms
+        command:
+            ["--log", "debug", "--kms_config", "/tmp/kms/config/kms02.yaml"]
+        volumes:
+            - ./config/goKMS/example02.yaml:/tmp/kms/config/kms02.yaml
+            - ./artifacts/ssl:/ssl
+        ports:
+            - "127.0.0.1:4402:1337"
+
+    kms03:
+        image: gokms
+        command:
+            ["--log", "debug", "--kms_config", "/tmp/kms/config/kms03.yaml"]
+        volumes:
+            - ./config/goKMS/example03.yaml:/tmp/kms/config/kms03.yaml
+            - ./artifacts/ssl:/ssl
+        ports:
+            - "127.0.0.1:4403:1337"
+
+    kms04:
+        image: gokms
+        command:
+            ["--log", "debug", "--kms_config", "/tmp/kms/config/kms04.yaml"]
+        volumes:
+            - ./config/goKMS/example04.yaml:/tmp/kms/config/kms04.yaml
+            - ./artifacts/ssl:/ssl
+        ports:
+            - "127.0.0.1:4404:1337"
+            - "127.0.0.1:9697:9696"
+
+    qlayer01:
+        image: quantumlayer
+        command: ["--config", "/tmp/quantumlayer/config/quantumlayer01.yaml"]
+        volumes:
+            - ./config/quantumlayer/example01.yaml:/tmp/quantumlayer/config/quantumlayer01.yaml
+
+    qlayer02:
+        image: quantumlayer
+        command: ["--config", "/tmp/quantumlayer/config/quantumlayer02.yaml"]
+        volumes:
+            - ./config/quantumlayer/example02.yaml:/tmp/quantumlayer/config/quantumlayer02.yaml
+
+    qlayer03:
+        image: quantumlayer
+        command: ["--config", "/tmp/quantumlayer/config/quantumlayer03.yaml"]
+        volumes:
+            - ./config/quantumlayer/example03.yaml:/tmp/quantumlayer/config/quantumlayer03.yaml
+
+    qlayer04:
+        image: quantumlayer
+        command: ["--config", "/tmp/quantumlayer/config/quantumlayer04.yaml"]
+        volumes:
+            - ./config/quantumlayer/example04.yaml:/tmp/quantumlayer/config/quantumlayer04.yaml
+
+    qlayer05:
+        image: quantumlayer
+        command: ["--config", "/tmp/quantumlayer/config/quantumlayer05.yaml"]
+        volumes:
+            - ./config/quantumlayer/example05.yaml:/tmp/quantumlayer/config/quantumlayer05.yaml
+
+    qlayer06:
+        image: quantumlayer
+        command: ["--config", "/tmp/quantumlayer/config/quantumlayer06.yaml"]
+        volumes:
+            - ./config/quantumlayer/example06.yaml:/tmp/quantumlayer/config/quantumlayer06.yaml
+
+    qlayer07:
+        image: quantumlayer
+        command: ["--config", "/tmp/quantumlayer/config/quantumlayer07.yaml"]
+        volumes:
+            - ./config/quantumlayer/example07.yaml:/tmp/quantumlayer/config/quantumlayer07.yaml
+
+    qlayer08:
+        image: quantumlayer
+        command: ["--config", "/tmp/quantumlayer/config/quantumlayer08.yaml"]
+        volumes:
+            - ./config/quantumlayer/example08.yaml:/tmp/quantumlayer/config/quantumlayer08.yaml
+
+    akms-receiver01:
+        image: akms-simulator
+
+    akms-receiver02:
+        image: akms-simulator
+
+    qkdn-controller:
+        image: registry.code.fbi.h-da.de/demoquandt/qkdn-controller:qkdn-main
+        volumes:
+            - ./config/controller/qkdn-gosdn.toml:/app/configs/qkdn-gosdn.toml
+            - ./config/controller/gNMISubscriptions.txt:/app/configs/gNMISubscriptions.txt
+        command: --config ./configs/qkdn-gosdn.toml
+        ports:
+            - "127.0.0.1:55055:55055"
+        environment:
+            GOSDN_ADMIN_PASSWORD: TestPassword
+
+    gosdnc:
+        image: registry.code.fbi.h-da.de/demoquandt/qkdn-controller/gosdnc:qkdn-main
+        volumes:
+            - ./config/controller/add_devices.sh:/scripts/add_devices.sh
+        entrypoint: ["/scripts/add_devices.sh"]
+
+    plugin-registry:
+        image: registry.code.fbi.h-da.de/demoquandt/qkdn-controller/plugin-registry:qkdn-main
+
+    mongo:
+        image: mongo:7
+        environment:
+            MONGO_INITDB_ROOT_USERNAME: root
+            MONGO_INITDB_ROOT_PASSWORD: example
+
+    rabbitmq:
+        image: rabbitmq:3-management
+
+    routing-app:
+        image: registry.code.fbi.h-da.de/demoquandt/qkdn-controller/routing-app:qkdn-main
+        entrypoint: ["./start_ra_sleep.sh"]
+        volumes:
+            - ./config/controller/start_ra_sleep.sh:/app/start_ra_sleep.sh
+            - ./config/controller/routing-config.yaml:/new/routing-config.yaml
diff --git a/goKMS/gnmiHandlers/kms/keyStoreHandler.go b/goKMS/gnmiHandlers/kms/keyStoreHandler.go
index 11e1d66f..8697fb06 100644
--- a/goKMS/gnmiHandlers/kms/keyStoreHandler.go
+++ b/goKMS/gnmiHandlers/kms/keyStoreHandler.go
@@ -42,27 +42,7 @@ func (yh *KeyStoreHandler) Init(config *handler.Config, publishToSubsFunc func([
 		return err
 	}
 
-	yh.Config.Lock()
-	defer yh.Config.Unlock()
-
-	copyCurrentConfig, err := ygot.DeepCopy(yh.Config.Data)
-	if err != nil {
-		return err
-	}
-
-	newConfig, ok := copyCurrentConfig.(*gnmitargetygot.Gnmitarget)
-	if !ok {
-		return fmt.Errorf("Wrong type, exptected: %T, got: %T", (*gnmitargetygot.OpenconfigInterfaces_Interfaces)(nil), copyCurrentConfig)
-	}
-
-	newConfig.GetOrCreateKeyStores()
-
-	//validate struct
-	if err := newConfig.Validate(); err != nil {
-		return err
-	}
-
-	yh.Config.Data = newConfig
+	yh.updateOrCreateKeyStores()
 
 	// Start the go routine that takes care of any update from the kms
 	go func() {
@@ -71,7 +51,7 @@ func (yh *KeyStoreHandler) Init(config *handler.Config, publishToSubsFunc func([
 			case <-yh.events:
 				log.Println("Update for key stores.")
 
-				diff, err := yh.updateOrCreateKeyStores(yh.kms)
+				diff, err := yh.updateOrCreateKeyStores()
 				if err != nil {
 					log.Errorf("Error within key stores subscription goroutine; %v", err)
 					break
@@ -90,7 +70,7 @@ func (yh *KeyStoreHandler) Update(c ygot.ValidatedGoStruct, jobs []*gnmi.Update)
 	return nil
 }
 
-func (yh *KeyStoreHandler) updateOrCreateKeyStores(kms *kms.KMS) ([]*gnmi.Notification, error) {
+func (yh *KeyStoreHandler) updateOrCreateKeyStores() ([]*gnmi.Notification, error) {
 	yh.Config.Lock()
 	defer yh.Config.Unlock()
 
@@ -104,7 +84,7 @@ func (yh *KeyStoreHandler) updateOrCreateKeyStores(kms *kms.KMS) ([]*gnmi.Notifi
 		return nil, fmt.Errorf("Wrong type, exptected: %T, got: %T", (*gnmitargetygot.Temp_KeyStores)(nil), copyCurrentConfig)
 	}
 
-	kmsPeers := kms.PeersDeepCopy()
+	kmsPeers := yh.kms.PeersDeepCopy()
 
 	confKeyStores := newConfig.GetOrCreateKeyStores()
 
diff --git a/goKMS/kms/kmsintercom.go b/goKMS/kms/kmsintercom.go
index 09c6bff8..344d20c8 100644
--- a/goKMS/kms/kmsintercom.go
+++ b/goKMS/kms/kmsintercom.go
@@ -128,7 +128,7 @@ func (s *kmsTalkerServer) SyncQkdBulk(ctx context.Context, in *pb.SyncQkdBulkReq
 		}
 	}
 
-	return nil, status.Errorf(codes.Unimplemented, "method SyncQkdBulk not implemented")
+	return nil, status.Errorf(codes.Internal, "Could not find a RawBulkKey that matches the provided IDs: %v", in.BulkId)
 }
 
 func (s *kmsTalkerServer) SyncKeyIdsForBulk(ctx context.Context, in *pb.SyncKeyIdsForBulkRequest) (*pb.SyncKeyIdsForBulkResponse, error) {
@@ -155,10 +155,8 @@ func (s *kmsTalkerServer) SyncKeyIdsForBulk(ctx context.Context, in *pb.SyncKeyI
 		return nil, status.Errorf(codes.Internal, "%v", err)
 	}
 
-	for keyId, key := range keyData {
-		if err := eqm.KeyStore().AddKey(keyId, key); err != nil {
-			log.Error(err)
-		}
+	if err := eqm.KeyStore().AddKeys(keyData); err != nil {
+		log.Error(err)
 	}
 
 	delete(eqm.RawBulkKeys, in.GetBulkId())
diff --git a/goKMS/kms/peers/danetQuantummodule.go b/goKMS/kms/peers/danetQuantummodule.go
index fd967f6b..b237a379 100644
--- a/goKMS/kms/peers/danetQuantummodule.go
+++ b/goKMS/kms/peers/danetQuantummodule.go
@@ -123,10 +123,8 @@ func (qm *DanetQuantumModule) Sync() error {
 		return err
 	}
 
-	for keyId, key := range keyData {
-		if err := qm.keyStore.AddKey(keyId, key); err != nil {
-			log.Error(err)
-		}
+	if err := qm.keyStore.AddKeys(keyData); err != nil {
+		log.Error(err)
 	}
 
 	qm.RawBulkKeysMutex.Lock()
diff --git a/goKMS/kms/quipsec.go b/goKMS/kms/quipsec.go
index da6c9c4e..4eb66b66 100644
--- a/goKMS/kms/quipsec.go
+++ b/goKMS/kms/quipsec.go
@@ -48,17 +48,23 @@ func (qs *quipSecServer) PushKeys(ctx context.Context, req *pb.PushKeysRequest)
 		return nil, status.Errorf(codes.Internal, "could not get bulkkeyid")
 	}
 
-	eqm.RawBulkKeysMutex.Lock()
-	defer eqm.RawBulkKeysMutex.Unlock()
 	if !eqm.IsActive() {
 		logrus.Debugf("Quantum module: %s is not active and denied incoming bulk keys", eqm.ID())
 		return nil, status.Errorf(codes.Aborted, "Currently no new bulk keys are accepted")
 	}
+	eqm.RawBulkKeysMutex.Lock()
 	eqm.RawBulkKeys[bulkKeyId] = &quantumlayer.QuantumLayerBulkKey{
 		BulkKeyId:     bulkKeyId,
 		BulkKeyLength: int(req.GetKeyBulk().GetKeyLength()),
 		BulkKey:       req.GetKeyBulk().Keys,
 	}
+	eqm.RawBulkKeysMutex.Unlock()
+
+	if eqm.KeyStore().Length() == 0 {
+		if err := eqm.Sync(); err != nil {
+			logrus.Error("Syncing key stores after a bulk key push failed; err: ", err)
+		}
+	}
 
 	logrus.Debugf("%s received a new bulk from: %s with id: %s and a length of: %d", qs.KMS.kmsName, qm.Address(), req.GetKeyBulk().GetKeyId(), req.GetKeyBulk().GetKeyLength())
 	return &pb.PushKeysResponse{Timestamp: time.Now().Unix()}, nil
diff --git a/goKMS/kms/store/kms-keystore.go b/goKMS/kms/store/kms-keystore.go
index 683c5634..297f1af5 100644
--- a/goKMS/kms/store/kms-keystore.go
+++ b/goKMS/kms/store/kms-keystore.go
@@ -50,7 +50,7 @@ func (ks *KmsKeyStore) Length() int {
 	return len(ks.keyStore)
 }
 
-func (ks *KmsKeyStore) AddKey(keyId uuid.UUID, keyToadd []byte) error {
+func (ks *KmsKeyStore) AddKey(keyId uuid.UUID, keyToAdd []byte) error {
 	ks.keyStoreMutex.Lock()
 	defer ks.keyStoreMutex.Unlock()
 
@@ -61,7 +61,7 @@ func (ks *KmsKeyStore) AddKey(keyId uuid.UUID, keyToadd []byte) error {
 
 	newKeyElement := &KmsKSElement{
 		KeyID:  keyId,
-		Key:    keyToadd,
+		Key:    keyToAdd,
 		Status: AVAILABLE,
 	}
 	// ok to add
@@ -77,6 +77,32 @@ func (ks *KmsKeyStore) AddKey(keyId uuid.UUID, keyToadd []byte) error {
 	return nil
 }
 
+func (ks *KmsKeyStore) AddKeys(keys map[uuid.UUID][]byte) error {
+	ks.keyStoreMutex.Lock()
+	defer ks.keyStoreMutex.Unlock()
+
+	// INFO: could be useful to also check for collisions
+
+	for keyId, keyToAdd := range keys {
+		newKeyElement := &KmsKSElement{
+			KeyID:  keyId,
+			Key:    keyToAdd,
+			Status: AVAILABLE,
+		}
+		// ok to add
+		ks.keyStore[newKeyElement.KeyID] = newKeyElement
+	}
+
+	// publish to eventBus
+	go func() {
+		err := ks.eventBus.Publish(event.NewKeyStoreEvent())
+		if err != nil {
+			fmt.Errorf("Publishing a key store update through the eventBus failed, err: %w", err)
+		}
+	}()
+	return nil
+}
+
 func (ks *KmsKeyStore) GetKey() (*KmsKSElement, error) {
 	ks.keyStoreMutex.Lock()
 	defer ks.keyStoreMutex.Unlock()
@@ -128,6 +154,7 @@ func (ks *KmsKeyStore) Reset() {
 }
 
 func AddETSIKeysToKeystore(keyStore *KmsKeyStore, keyContainer []etsi14.KeyContainerKeysInner) error {
+	keysToAdd := make(map[uuid.UUID][]byte)
 	for _, keyItem := range keyContainer {
 		// decode base64 encoded key string
 		key, err := base64.StdEncoding.DecodeString(keyItem.GetKey())
@@ -138,10 +165,11 @@ func AddETSIKeysToKeystore(keyStore *KmsKeyStore, keyContainer []etsi14.KeyConta
 		if err != nil {
 			return err
 		}
-		// add to keystore
-		if err := keyStore.AddKey(keyId, key); err != nil {
-			log.Error(err)
-		}
+		keysToAdd[keyId] = key
+	}
+	// add to keystore
+	if err := keyStore.AddKeys(keysToAdd); err != nil {
+		log.Error(err)
 	}
 	log.Debugf("Current key store length: %d", keyStore.Length())
 	return nil
-- 
GitLab