diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e5384cb9bbf91e301b4c00b57144fa5c2fba8167..e2b42c533f8b692041e4eb36f97c1640707fd6cc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -157,6 +157,8 @@ integration-test-kms: INTEGRATION_TEST_KMS1_AKMS_URL: kms_1:9696 INTEGRATION_TEST_LOG_FILE1_URL: akms-simulator_1:4444 INTEGRATION_TEST_LOG_FILE2_URL: akms-simulator_2:4444 + INTEGRATION_TEST_KMS1_ETSI14_URL: kms_1:1414 + INTEGRATION_TEST_KMS2_ETSI14_URL: kms_2:1414 services: - name: $IMAGE_PATH/akms-simulator:$CI_COMMIT_REF_SLUG alias: akms-simulator_1 diff --git a/goKMS/etsi/etsi14/etsi14Server/server.go b/goKMS/etsi/etsi14/etsi14Server/server.go index f9912f0b5d7bed037ad3532c7a0bf8821f75e09a..94b7750317a25c22c960172c49b1f6a37d821ebb 100644 --- a/goKMS/etsi/etsi14/etsi14Server/server.go +++ b/goKMS/etsi/etsi14/etsi14Server/server.go @@ -18,6 +18,8 @@ import ( "github.com/sirupsen/logrus" ) +const etsi014RequestID = "etsi014" + type ETSI14RESTService struct { serviceAddress string remoteCKMSID uuid.UUID @@ -204,7 +206,7 @@ func (s *ETSI14RESTService) GetStatus(ctx context.Context, slaveSAEID string) (r // getKeyContainerFromKeyExchange starts the key exchange using the underlying QKD forwarding and returns the resulting KSA keys. func (s *ETSI14RESTService) getKeyContainerFromKeyExchange(number int64) (*restserver.KeyContainer, error) { - keys, err := s.kms.ExchangeKeyAfterETSI14GetKeyRequest(s.remoteCKMSID, number) // Note: we should have a mapping mechanism here to support multiple endpoints in the future + keys, err := s.kms.ExchangeKeyAfterETSI14GetKeyRequest(s.remoteCKMSID, number, etsi014RequestID) // Note: we should have a mapping mechanism here to support multiple endpoints in the future if err != nil { return nil, err } diff --git a/goKMS/kms/kms.go b/goKMS/kms/kms.go index 67e2f7bd2986a63a1176921e3dea3f15c5ef888c..7948cd69ac43ddf0f5bcd11fa778b99cc51781e0 100644 --- a/goKMS/kms/kms.go +++ b/goKMS/kms/kms.go @@ -634,7 +634,7 @@ func (kms *KMS) sendKSAKeysToPlatformKmsPeer(kmsPeerAddress, platformKeyID, requ return nil } -func (kms *KMS) ExchangeKeyAfterETSI14GetKeyRequest(receivingCKMSID uuid.UUID, number int64) ([]client.KSAKey, error) { +func (kms *KMS) ExchangeKeyAfterETSI14GetKeyRequest(receivingCKMSID uuid.UUID, number int64, requestID string) ([]client.KSAKey, error) { // CreateRouteRequest pathID := uuid.New() log.Debugf("(ETSI14) created new path id: %s, for incoming ETSI14 key request", pathID) @@ -662,10 +662,10 @@ func (kms *KMS) ExchangeKeyAfterETSI14GetKeyRequest(receivingCKMSID uuid.UUID, n } // GenerateAndSend - return kms.generateAndReturnKsaKey(receivingCKMSID, pathID, number) + return kms.generateAndReturnKsaKey(receivingCKMSID, pathID, number, requestID) } -func (kms *KMS) generateAndReturnKsaKey(receivingCKMSID, pathID uuid.UUID, number int64) ([]client.KSAKey, error) { +func (kms *KMS) generateAndReturnKsaKey(receivingCKMSID, pathID uuid.UUID, number int64, requestID string) ([]client.KSAKey, error) { if number < 1 { log.Errorf("number must be positive and at least 1, provided: %d\n", number) return nil, fmt.Errorf("number must be positive and at least 1, provided: %d", number) @@ -700,7 +700,7 @@ func (kms *KMS) generateAndReturnKsaKey(receivingCKMSID, pathID uuid.UUID, numbe remoteKMSAdrress := fmt.Sprintf("%s:%d", remoteKMS.Address, remoteKMS.Port) - err = kms.sendKSAKeysToPlatformKmsPeer(remoteKMSAdrress, platformKey.Id.String(), "", ksaKeysToSendToRemoteKMS) + err = kms.sendKSAKeysToPlatformKmsPeer(remoteKMSAdrress, platformKey.Id.String(), requestID, ksaKeysToSendToRemoteKMS) if err != nil { log.Error(err) return nil, err diff --git a/goKMS/kms/kmsintercom.go b/goKMS/kms/kmsintercom.go index e6e3949fcd4d1951fe94bec466e91e401f397fa9..00d8806cbe6c489cc8c5a5398cfb4173f5ea9cce 100644 --- a/goKMS/kms/kmsintercom.go +++ b/goKMS/kms/kmsintercom.go @@ -25,6 +25,8 @@ import ( "google.golang.org/grpc/status" ) +const etsi014RequestID = "etsi014" + type kmsTalkerServer struct { pb.UnimplementedKmsTalkerServer keyNegotationMutex sync.Mutex @@ -328,7 +330,7 @@ func (s *kmsTalkerServer) KeyDelivery(ctx context.Context, in *pb.KeyDeliveryReq } } - if s.KMS.KeyStoreChannel != nil { + if s.KMS.KeyStoreChannel != nil && in.GetRequestId() == etsi014RequestID { log.Debugf("(ETSI14) Pushing to KeyStoreChannel: %v in %s", s.KMS.KeyStoreChannel, s.KMS.kmsName) s.KMS.KeyStoreChannel <- akmsKSAKeys } else if s.KMS.CKMSAkmsClient != nil { diff --git a/integration-tests/code/etsi14GetKeyTest/etsi14_GetKey_test.go b/integration-tests/code/etsi14GetKeyTest/etsi14_GetKey_test.go new file mode 100644 index 0000000000000000000000000000000000000000..36d01bac89836db6022402375a1c59d739df3145 --- /dev/null +++ b/integration-tests/code/etsi14GetKeyTest/etsi14_GetKey_test.go @@ -0,0 +1,146 @@ +package integration_tests + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "os" + "strings" + "testing" + "time" + + integration_test_utils "code.fbi.h-da.de/danet/quant/integration-tests/code/integrationTestUtils" + "github.com/stretchr/testify/assert" +) + +func TestETSI14GetKey(t *testing.T) { //nolint:gocyclo + kms2URL := "127.0.0.1:7031" + kms2URL_ENV := os.Getenv("INTEGRATION_TEST_KMS2_URL") + if kms2URL_ENV != "" { + kms2URL = kms2URL_ENV + } + kms1URL := "127.0.0.1:7030" + kms1URL_ENV := os.Getenv("INTEGRATION_TEST_KMS1_URL") + if kms1URL_ENV != "" { + kms1URL = kms1URL_ENV + } + kms1ETSI14URL := "127.0.0.1:1414" + kms1ETSI14URL_ENV := os.Getenv("INTEGRATION_TEST_KMS1_ETSI14_URL") + if kms1ETSI14URL_ENV != "" { + kms1ETSI14URL = kms1ETSI14URL_ENV + } + kms2ETSI14URL := "127.0.0.1:1415" + kms2ETSI14URL_ENV := os.Getenv("INTEGRATION_TEST_KMS2_ETSI14_URL") + if kms2ETSI14URL_ENV != "" { + kms2ETSI14URL = kms2ETSI14URL_ENV + } + + url := fmt.Sprintf("http://%s/api/v1/keys/slave_SAE_ID/enc_keys", kms1ETSI14URL) + data := ETSI14RequestData{ + Number: 1, + } + + jsonData, err := json.Marshal(data) + if err != nil { + fmt.Println(err) + return + } + + var respKms1 *http.Response + go func() { + respKms1, err = http.Post(url, "application/json", bytes.NewBuffer(jsonData)) + if err != nil { + t.Errorf("Error making HTTP request: %s", err) + return + } + + if respKms1.StatusCode != http.StatusOK { + t.Errorf("Expected status code 200 OK, but got %d", respKms1.StatusCode) + } + }() + + time.Sleep(time.Duration(2) * time.Second) + + output, err := integration_test_utils.GnmicCommand(kms1URL, "get", "--path", "create-route-requests") + if err != nil { + t.Errorf("Error getting create-route-requests: %s; %s", err, output) + } + + output = strings.Split(output, "\"kms-path-id\": \"")[1] + output = strings.Split(output, "\",")[0] + + path := fmt.Sprintf("key-routing-sessions/routing-sessions[path-id=%s]", output) + + config01 := integration_test_utils.BuildKms1RoutingConfig(path, output) + + config02 := integration_test_utils.BuildKms2RoutingConfig(path, output) + + argsKMS1 := []string{"set"} + for _, update := range config01 { + argsKMS1 = append(argsKMS1, "--update-path", update.Path, "--update-value", update.JSON) + } + + argsKMS2 := []string{"set"} + for _, update := range config02 { + argsKMS2 = append(argsKMS2, "--update-path", update.Path, "--update-value", update.JSON) + } + + output, err = integration_test_utils.GnmicCommand(kms2URL, argsKMS2...) + if err != nil { + t.Errorf("Error setting routing-session: %s; %s", err, output) + } + + output, err = integration_test_utils.GnmicCommand(kms1URL, argsKMS1...) + if err != nil { + t.Errorf("Error setting routing-session: %s; %s", err, output) + } + + time.Sleep(time.Duration(2) * time.Second) + + kms1KeyContainer, err := getKeyContainerFromResponse(respKms1) + if err != nil { + t.Errorf("Error getting Key Container from resp: %v, err: %v", respKms1, err) + } + + assert.NotNil(t, kms1KeyContainer.Keys) + + url = fmt.Sprintf("http://%s/api/v1/keys/master_SAE_ID/dec_keys", kms2ETSI14URL) + data = ETSI14RequestData{ + KeyIDs: []KeyIdsRequestKeyIdsInner{ + { + KeyID: kms1KeyContainer.Keys[0].KeyID, + }, + }, + } + + jsonData, err = json.Marshal(data) + if err != nil { + fmt.Println(err) + return + } + + var respKms2 *http.Response + go func() { + respKms2, err = http.Post(url, "application/json", bytes.NewBuffer(jsonData)) + if err != nil { + t.Errorf("Error making HTTP request: %s", err) + return + } + + if respKms2.StatusCode != http.StatusOK { + t.Errorf("Expected status code 200 OK, but got %d", respKms2.StatusCode) + } + }() + + time.Sleep(time.Duration(2) * time.Second) + + kms2KeyContainer, err := getKeyContainerFromResponse(respKms2) + if err != nil { + t.Errorf("Error getting Key Container from resp: %v, err: %v", respKms1, err) + } + + assert.NotNil(t, kms2KeyContainer.Keys) + + assert.Equal(t, kms1KeyContainer, kms2KeyContainer) +} diff --git a/integration-tests/code/etsi14GetKeyTest/etsi14_GetKey_utility.go b/integration-tests/code/etsi14GetKeyTest/etsi14_GetKey_utility.go new file mode 100644 index 0000000000000000000000000000000000000000..98188acd5f0f82e97d9a0ec45809aae04a68cc1c --- /dev/null +++ b/integration-tests/code/etsi14GetKeyTest/etsi14_GetKey_utility.go @@ -0,0 +1,42 @@ +package integration_tests + +import ( + "encoding/json" + "io" + "net/http" +) + +type ETSI14RequestData struct { + Number int64 `json:"number,omitempty"` + KeyIDs []KeyIdsRequestKeyIdsInner `json:"key_IDs,omitempty"` +} + +type KeyIdsRequestKeyIdsInner struct { + KeyID string `json:"key_ID"` +} + +type ETSI14ResponseData struct { + Keys []KeyContainerKeysInner `json:"Keys,omitempty"` +} + +type KeyContainerKeysInner struct { + KeyID string `json:"key_ID,omitempty"` + + Key string `json:"key,omitempty"` +} + +func getKeyContainerFromResponse(kmsResp *http.Response) (*ETSI14ResponseData, error) { + defer kmsResp.Body.Close() //nolint:errcheck + body, err := io.ReadAll(kmsResp.Body) + if err != nil { + return nil, err + } + + kmsKeyContainer := &ETSI14ResponseData{} + err = json.Unmarshal([]byte(body), kmsKeyContainer) + if err != nil { + return nil, err + } + + return kmsKeyContainer, nil +} diff --git a/integration-tests/code/getKSAKeyTest/getKSA_key_test.go b/integration-tests/code/getKSAKeyTest/getKSA_key_test.go index f042522a074f9fedeacf26582d626ba8be7a4a7e..ba39bc2b0a7e499b019220c4f6d02b11daed8e88 100644 --- a/integration-tests/code/getKSAKeyTest/getKSA_key_test.go +++ b/integration-tests/code/getKSAKeyTest/getKSA_key_test.go @@ -17,12 +17,6 @@ import ( "github.com/stretchr/testify/assert" ) -type Update struct { - Path string - Value string - JSON string -} - // For log file. type LogFile struct { Source string `json:"source"` @@ -125,67 +119,9 @@ func TestGetKSAKey(t *testing.T) { //nolint:gocyclo path := fmt.Sprintf("key-routing-sessions/routing-sessions[path-id=%s]", output) - config01 := []Update{ - { - Path: path, - JSON: fmt.Sprintf(`{"path-id": "%s"}`, output), - }, - { - Path: fmt.Sprint(path, "/next-hop"), - JSON: fmt.Sprintf(`{"node-id": "%s"}`, "5e41c291-6121-4335-84f6-41e04b8bdaa2"), - }, - { - Path: fmt.Sprint(path, "/next-hop"), - JSON: fmt.Sprintf(`{"hostname": "%s"}`, "kms_2"), - }, - { - Path: fmt.Sprint(path, "/next-hop"), - JSON: fmt.Sprintf(`{"port": %d}`, 50910), - }, - { - Path: fmt.Sprint(path, "/initiating-kms-address"), - JSON: fmt.Sprintf(`{"node-id": "%s"}`, "5e41c291-6121-4335-84f6-41e04b8bdaa2"), - }, - { - Path: fmt.Sprint(path, "/initiating-kms-address"), - JSON: fmt.Sprintf(`{"hostname": "%s"}`, "kms_2"), - }, - { - Path: fmt.Sprint(path, "/initiating-kms-address"), - JSON: fmt.Sprintf(`{"port": %d}`, 50910), - }, - } + config01 := integration_test_utils.BuildKms1RoutingConfig(path, output) - config02 := []Update{ - { - Path: path, - JSON: fmt.Sprintf(`{"path-id": "%s"}`, output), - }, - { - Path: fmt.Sprint(path, "/prev-hop"), - JSON: fmt.Sprintf(`{"node-id": "%s"}`, "0ff33c82-7fe1-482b-a0ca-67565806ee4b"), - }, - { - Path: fmt.Sprint(path, "/prev-hop"), - JSON: fmt.Sprintf(`{"hostname": "%s"}`, "kms_1"), - }, - { - Path: fmt.Sprint(path, "/prev-hop"), - JSON: fmt.Sprintf(`{"port": %d}`, 50910), - }, - { - Path: fmt.Sprint(path, "/initiating-kms-address"), - JSON: fmt.Sprintf(`{"node-id": "%s"}`, "0ff33c82-7fe1-482b-a0ca-67565806ee4b"), - }, - { - Path: fmt.Sprint(path, "/initiating-kms-address"), - JSON: fmt.Sprintf(`{"hostname": "%s"}`, "kms_1"), - }, - { - Path: fmt.Sprint(path, "/initiating-kms-address"), - JSON: fmt.Sprintf(`{"port": %d}`, 50910), - }, - } + config02 := integration_test_utils.BuildKms2RoutingConfig(path, output) argsKMS1 := []string{"set"} for _, update := range config01 { diff --git a/integration-tests/code/integrationTestUtils/integrationTestUtils.go b/integration-tests/code/integrationTestUtils/integrationTestUtils.go index 856d96465c1dd29419b4e0d2d3560aaac70ae1e6..19ed596a2733311e2d6162f64fbb46ae99fc789e 100644 --- a/integration-tests/code/integrationTestUtils/integrationTestUtils.go +++ b/integration-tests/code/integrationTestUtils/integrationTestUtils.go @@ -1,9 +1,16 @@ package utils import ( + "fmt" "os/exec" ) +type Update struct { + Path string + Value string + JSON string +} + func GnmicCommand(address string, args ...string) (string, error) { cmd := exec.Command("gnmic", "-a", address, "-u", "admin", "-p", "admin", "--insecure", "-e", "JSON_IETF") cmd.Args = append(cmd.Args, args...) @@ -15,3 +22,69 @@ func GnmicCommand(address string, args ...string) (string, error) { } return outputString, nil } + +func BuildKms1RoutingConfig(path, pathID string) []Update { + return []Update{ + { + Path: path, + JSON: fmt.Sprintf(`{"path-id": "%s"}`, pathID), + }, + { + Path: fmt.Sprint(path, "/next-hop"), + JSON: fmt.Sprintf(`{"node-id": "%s"}`, "5e41c291-6121-4335-84f6-41e04b8bdaa2"), + }, + { + Path: fmt.Sprint(path, "/next-hop"), + JSON: fmt.Sprintf(`{"hostname": "%s"}`, "kms_2"), + }, + { + Path: fmt.Sprint(path, "/next-hop"), + JSON: fmt.Sprintf(`{"port": %d}`, 50910), + }, + { + Path: fmt.Sprint(path, "/initiating-kms-address"), + JSON: fmt.Sprintf(`{"node-id": "%s"}`, "5e41c291-6121-4335-84f6-41e04b8bdaa2"), + }, + { + Path: fmt.Sprint(path, "/initiating-kms-address"), + JSON: fmt.Sprintf(`{"hostname": "%s"}`, "kms_2"), + }, + { + Path: fmt.Sprint(path, "/initiating-kms-address"), + JSON: fmt.Sprintf(`{"port": %d}`, 50910), + }, + } +} + +func BuildKms2RoutingConfig(path, pathID string) []Update { + return []Update{ + { + Path: path, + JSON: fmt.Sprintf(`{"path-id": "%s"}`, pathID), + }, + { + Path: fmt.Sprint(path, "/prev-hop"), + JSON: fmt.Sprintf(`{"node-id": "%s"}`, "0ff33c82-7fe1-482b-a0ca-67565806ee4b"), + }, + { + Path: fmt.Sprint(path, "/prev-hop"), + JSON: fmt.Sprintf(`{"hostname": "%s"}`, "kms_1"), + }, + { + Path: fmt.Sprint(path, "/prev-hop"), + JSON: fmt.Sprintf(`{"port": %d}`, 50910), + }, + { + Path: fmt.Sprint(path, "/initiating-kms-address"), + JSON: fmt.Sprintf(`{"node-id": "%s"}`, "0ff33c82-7fe1-482b-a0ca-67565806ee4b"), + }, + { + Path: fmt.Sprint(path, "/initiating-kms-address"), + JSON: fmt.Sprintf(`{"hostname": "%s"}`, "kms_1"), + }, + { + Path: fmt.Sprint(path, "/initiating-kms-address"), + JSON: fmt.Sprintf(`{"port": %d}`, 50910), + }, + } +} diff --git a/integration-tests/config/kms/kms_1.yaml b/integration-tests/config/kms/kms_1.yaml index 273b444090a9b320d6ae5aa5dcb9c9a6a4df03bc..4c7a9289c228f4055399ed1434221e0308a59da3 100644 --- a/integration-tests/config/kms/kms_1.yaml +++ b/integration-tests/config/kms/kms_1.yaml @@ -20,3 +20,6 @@ Peers: QuantumModule: Type: emulated Hostname: quantumlayer_1 +ETSI14Server: + Address: ":1414" + RemoteCKMSID: "5e41c291-6121-4335-84f6-41e04b8bdaa2" diff --git a/integration-tests/config/kms/kms_2.yaml b/integration-tests/config/kms/kms_2.yaml index 319da986a4f47b927cdaa595062a8c016b96fe64..a887c49ce1053e442cdcd112ba1a87ad580bc573 100644 --- a/integration-tests/config/kms/kms_2.yaml +++ b/integration-tests/config/kms/kms_2.yaml @@ -20,3 +20,6 @@ Peers: QuantumModule: Type: emulated Hostname: quantumlayer_2 +ETSI14Server: + Address: ":1414" + RemoteCKMSID: "0ff33c82-7fe1-482b-a0ca-67565806ee4b" diff --git a/integration-tests/docker-compose_integration_test.yml b/integration-tests/docker-compose_integration_test.yml index 8576fc0a3f841292090c17394f74fab01f39e613..80eed98526f897103962b9f63c0ea41719409abd 100644 --- a/integration-tests/docker-compose_integration_test.yml +++ b/integration-tests/docker-compose_integration_test.yml @@ -14,6 +14,7 @@ services: ports: - "127.0.0.1:7030:7030" - "127.0.0.1:9696:9696" + - "127.0.0.1:1414:1414" kms_2: image: gokms @@ -29,6 +30,7 @@ services: - ../artifacts/integration-tests/ssl:/config/ssl ports: - "127.0.0.1:7031:7030" + - "127.0.0.1:1415:1414" quantumlayer_1: image: quantumlayer