diff --git a/integration-tests/code/testRestartOfKMSTest/testRestartOfKMS_test.go b/integration-tests/code/testRestartOfKMSTest/testRestartOfKMS_test.go new file mode 100644 index 0000000000000000000000000000000000000000..2ffe1c154260562c78a99f7d83ec20f2a8647a7e --- /dev/null +++ b/integration-tests/code/testRestartOfKMSTest/testRestartOfKMS_test.go @@ -0,0 +1,248 @@ +package integration_tests + +import ( + "bytes" + "encoding/json" + "fmt" + "time" + + "io" + "net/http" + "os" + "testing" + + "code.fbi.h-da.de/danet/quant/goKMS/config" + kmstls "code.fbi.h-da.de/danet/quant/goKMS/kms/tls" + utils "code.fbi.h-da.de/danet/quant/integration-tests/code/integrationTestUtils" + "github.com/google/uuid" + "github.com/stretchr/testify/assert" +) + +// For log file. +type LogFile struct { + Source string `json:"source"` + Body PushKSAKeyRequest `json:"body"` +} +type PushKSAKeyRequest struct { + RequestID string `json:"request_ID"` + ProcessID string `json:"process_ID"` + KSAKeys []KSAKey `json:"ksa_keys"` +} + +type KSAKey struct { + KeyID string `json:"key_ID"` + Key string `json:"key"` +} + +// For request. +type KeyProperties struct { + Number int `json:"number"` + KeyLength int `json:"key_length"` + Timeout int `json:"timeout"` + TTL int `json:"TTL"` +} + +type RequestData struct { + ReceivingCKMSID string `json:"receiving_CKMS_ID"` + RequestID string `json:"request_ID"` + KeyProperties KeyProperties `json:"key_properties"` +} + +func TestRestartOfKMS(t *testing.T) { //nolint:gocyclo + gosdncScript := "../../config/gosdnc/add_devices.sh" + gosdncScript_ENV := os.Getenv("INTEGRATION_TEST_GOSDNC_SCRIPT") + if gosdncScript_ENV != "" { + gosdncScript = gosdncScript_ENV + } + cleanupScript := "../../config/gosdnc/delete_devices.sh" + cleanupScript_ENV := os.Getenv("INTEGRATION_TEST_CLEANUP_SCRIPT") + if cleanupScript_ENV != "" { + cleanupScript = cleanupScript_ENV + } + controllerURL := "127.0.0.1:55055" + controllerURL_ENV := os.Getenv("INTEGRATION_TEST_CONTROLLER_URL") + if controllerURL_ENV != "" { + controllerURL = controllerURL_ENV + } + kms1AkmsURL := "127.0.0.1:9696" + kms1AkmsURL_ENV := os.Getenv("INTEGRATION_TEST_KMS1_AKMS_URL") + if kms1AkmsURL_ENV != "" { + kms1AkmsURL = kms1AkmsURL_ENV + } + logFileURL := "127.0.0.1:4444" + logFileURL_ENV := os.Getenv("INTEGRATION_TEST_LOG_FILE1_URL") + if logFileURL_ENV != "" { + logFileURL = logFileURL_ENV + } + logFileURL2 := "127.0.0.1:4445" + logFileURL_ENV2 := os.Getenv("INTEGRATION_TEST_LOG_FILE2_URL") + if logFileURL_ENV2 != "" { + logFileURL2 = logFileURL_ENV2 + } + + // Tell the qkdn-controller what devices to use. + _, err := utils.RunGosdncScript(gosdncScript, controllerURL) + if err != nil { + currentFolderPath := os.Getenv("PWD") + t.Errorf("Error running gosdnc script. Current folder path: %s, Error: %s", currentFolderPath, err) + } + defer utils.RunGosdncScript(cleanupScript, controllerURL) //nolint:errcheck + + clients := getHttpClients(t) + + for testRun := range []int{0, 1} { + cleanupLogFiles(t, clients, []string{logFileURL, logFileURL2}) + requestId := uuid.New().String() + + url := fmt.Sprintf("https://%s/api/v1/keys/ksa_key_req", kms1AkmsURL) + data := RequestData{ + ReceivingCKMSID: "5e41c291-6121-4335-84f6-41e04b8bdaa2", + RequestID: requestId, + KeyProperties: KeyProperties{ + Number: 1, + KeyLength: 256, + Timeout: 20, + TTL: 24, + }, + } + + jsonData, err := json.Marshal(data) + if err != nil { + fmt.Println(err) + return + } + + resp, err := clients[0].Post(url, "application/json", bytes.NewBuffer(jsonData)) + if err != nil { + t.Errorf("Error making HTTP request: %s", err) + return + } + defer resp.Body.Close() //nolint:errcheck + + if resp.StatusCode != http.StatusNoContent { + t.Errorf("Expected status code 204 No Content, but got %d", resp.StatusCode) + } + + // Get logfile of akms + resp, err = clients[0].Get("https://" + logFileURL + "/debug/get_log_file") + if err != nil { + t.Errorf("Error making HTTP request: %s", err) + return + } + defer resp.Body.Close() //nolint:errcheck + + body, err := io.ReadAll(resp.Body) + if err != nil { + t.Errorf("Error reading response body: %s", err) + return + } + + var logFile LogFile + err = json.Unmarshal(body, &logFile) + if err != nil { + t.Errorf("Error parsing logFile answer from AKMS: %s. \n Most likely the AKMS never received a ksa key. It told us: %s", err, string(body)) + return + } + assert.NotNil(t, logFile.Source) + assert.Equal(t, requestId, logFile.Body.RequestID) + assert.NotNil(t, logFile.Body.ProcessID) + assert.Equal(t, 1, len(logFile.Body.KSAKeys)) + assert.NotNil(t, logFile.Body.KSAKeys[0].KeyID) + assert.NotNil(t, logFile.Body.KSAKeys[0].Key) + + time.Sleep(5 * time.Second) + resp, err = clients[1].Get("https://" + logFileURL2 + "/debug/get_log_file") + if err != nil { + t.Errorf("Error making HTTP request: %s", err) + return + } + defer resp.Body.Close() //nolint:errcheck + + body, err = io.ReadAll(resp.Body) + if err != nil { + t.Errorf("Error reading response body: %s", err) + return + } + var logFile2 LogFile + + err = json.Unmarshal(body, &logFile2) + if err != nil { + t.Errorf("Error parsing logFile answer from AKMS: %s. \n Most likely the AKMS never received a ksa key. It told us: %s", err, string(body)) + return + } + assert.NotNil(t, logFile2.Source) + assert.Equal(t, requestId, logFile2.Body.RequestID) + assert.NotNil(t, logFile2.Body.ProcessID) + assert.Equal(t, 1, len(logFile2.Body.KSAKeys)) + assert.NotNil(t, logFile2.Body.KSAKeys[0].KeyID) + assert.NotNil(t, logFile2.Body.KSAKeys[0].Key) + + // Check that both log files are identical except for the source. + assert.NotEqual(t, logFile.Source, logFile2.Source) + assert.Equal(t, logFile.Body.RequestID, logFile2.Body.RequestID) + assert.Equal(t, logFile.Body.ProcessID, logFile2.Body.ProcessID) + assert.Equal(t, logFile.Body.KSAKeys[0].KeyID, logFile2.Body.KSAKeys[0].KeyID) + assert.Equal(t, logFile.Body.KSAKeys[0].Key, logFile2.Body.KSAKeys[0].Key) + + if testRun == 0 { + // Restart KMS1 + err = utils.RestartKMS("../../docker-compose.yml", 2) + if err != nil { + t.Errorf("Error restarting KMS: %s", err) + return + } + time.Sleep(5 * time.Second) + } + } +} + +func getHttpClients(t *testing.T) []*http.Client { + // Get the clients for the two AKMS simulators. + // AKMS1 + tlsConfig := config.TLSConfig{ + Active: true, + CAFile: "../../../artifacts/integration-tests/ssl/ca.crt", + CertFile: "../../../artifacts/integration-tests/ssl/kms/kms1-selfsigned.crt", + KeyFile: "../../../artifacts/integration-tests/ssl/kms/kms1-selfsigned.key", + } + + tlsConf, err := kmstls.GenerateTLSLibraryConfig(tlsConfig) + if err != nil { + t.Errorf("Error generating TLS config: %s", err) + } + transport := &http.Transport{ + TLSClientConfig: tlsConf, + } + client1 := &http.Client{Transport: transport} + + // AKMS2 + tlsConfig = config.TLSConfig{ + Active: true, + CAFile: "../../../artifacts/integration-tests/ssl/ca.crt", + CertFile: "../../../artifacts/integration-tests/ssl/kms/kms2-selfsigned.crt", + KeyFile: "../../../artifacts/integration-tests/ssl/kms/kms2-selfsigned.key", + } + + tlsConf, err = kmstls.GenerateTLSLibraryConfig(tlsConfig) + if err != nil { + t.Errorf("Error generating TLS config: %s", err) + } + transport = &http.Transport{ + TLSClientConfig: tlsConf, + } + client2 := &http.Client{Transport: transport} + + return []*http.Client{client1, client2} +} + +func cleanupLogFiles(t *testing.T, clients []*http.Client, logFileURLs []string) { + for i, url := range logFileURLs { + // Make sure logFiles for akms_simulator_1 don't exist. + request, _ := http.NewRequest("DELETE", "https://"+url+"/debug/get_log_file", nil) + _, err := clients[i].Do(request) + if err != nil { + t.Errorf("Error making HTTP request: %s", err) + return + } + } +}