From 9b05915850a49d6e5baa748172b6961ca7d8f419 Mon Sep 17 00:00:00 2001 From: Neil-Jocelyn Schark <neil.schark@h-da.de> Date: Thu, 5 Dec 2024 15:26:07 +0000 Subject: [PATCH] Simple longevity tests See merge request danet/quant!215 --- .devcontainer/devcontainer.json | 8 +- .gitignore | 2 + .vscode/launch.json | 4 +- Makefile | 27 +++- README.md | 5 + akms-simulator/Dockerfile | 1 + akms-simulator/akms-simulator.go | 19 ++- .../testRestartOfKMS_test.go | 6 +- integration-tests/docker-compose-otp.yml | 111 -------------- .../docker-compose.override.otp.yml | 16 +++ longevity-tests/docker-compose.yml | 136 ++++++++++++++++++ longevity-tests/longevity.py | 115 +++++++++++++++ longevity-tests/run-curl.sh | 22 +++ 13 files changed, 343 insertions(+), 129 deletions(-) delete mode 100644 integration-tests/docker-compose-otp.yml create mode 100644 integration-tests/docker-compose.override.otp.yml create mode 100644 longevity-tests/docker-compose.yml create mode 100644 longevity-tests/longevity.py create mode 100755 longevity-tests/run-curl.sh diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index cd96c21d..04de559d 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -15,7 +15,10 @@ "ghcr.io/devcontainers/features/docker-in-docker:2.12": { "version": "latest", "dockerDashComposeVersion": "v2" - } + }, + "ghcr.io/devcontainers/features/python:1": { + "version": "3.12" + } }, // add any required extensions that must be pre-installed in the devcontainer "customizations": { @@ -30,7 +33,8 @@ "valentjn.vscode-ltex", "zxh404.vscode-proto3", "typefox.yang-vscode", - "mechatroner.rainbow-csv" + "mechatroner.rainbow-csv", + "ms-python.autopep8" ] } }, diff --git a/.gitignore b/.gitignore index ba1c1ed9..4ff652cf 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,5 @@ gostructs.go *.out .gosdnc.toml + +longevity-tests/akms* diff --git a/.vscode/launch.json b/.vscode/launch.json index 70f8fa1d..cbc246ef 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -130,8 +130,8 @@ { "name": "Debug open integration test and kms", "configurations": [ - "integration-test-kms01-debug", - "integration-test-kms02-debug", + "integration-test-aes-kms01-debug", + "integration-test-aes-kms02-debug", "Launch currently open test" ], "stopAll": true diff --git a/Makefile b/Makefile index 4a96cdf3..69fba2af 100644 --- a/Makefile +++ b/Makefile @@ -119,19 +119,32 @@ integration-test-aes-debug-compose-down: docker compose -f integration-tests/docker-compose.yml -f integration-tests/docker-compose.override.debug.yml down integration-test-otp: install-gosdnc generate-integration-test-certs build-images - docker compose -f integration-tests/docker-compose-otp.yml down - docker compose -f integration-tests/docker-compose-otp.yml up -d + docker compose -f integration-tests/docker-compose.yml -f integration-tests/docker-compose.override.otp.yml down + docker compose -f integration-tests/docker-compose.yml -f integration-tests/docker-compose.override.otp.yml up -d echo "Will sleep for the quantumlayers to get ready" sleep 45 go test -p 1 -count=1 -v ./integration-tests/code/* - docker compose -f integration-tests/docker-compose-otp.yml down + docker compose -f integration-tests/docker-compose.yml -f integration-tests/docker-compose.override.otp.yml down integration-test-otp-debug-compose-up: generate-integration-test-certs build-images install-gosdnc - docker compose -f integration-tests/docker-compose-otp.yml -f integration-tests/docker-compose.override.debug.yml down - docker compose -f integration-tests/docker-compose-otp.yml -f integration-tests/docker-compose.override.debug.yml up -d + docker compose -f integration-tests/docker-compose.yml -f integration-tests/docker-compose.override.debug.yml down + docker compose -f integration-tests/docker-compose.yml -f integration-tests/docker-compose.override.debug.yml up -d integration-test-otp-debug-compose-down: - docker compose -f integration-tests/docker-compose-otp.yml -f integration-tests/docker-compose.override.debug.yml down + docker compose -f integration-tests/docker-compose.yml -f integration-tests/docker-compose.override.debug.yml down + +longevity-test: generate-gokms-certs build-images install-gosdnc + rm -rf longevity-tests/akms1-logs + rm -rf longevity-tests/akms2-logs + docker compose -f longevity-tests/docker-compose.yml down + docker compose -f longevity-tests/docker-compose.yml up -d + echo "Will add devices, can take a while" + ./config/controller/add_devices.sh + sleep 10 + python3 longevity-tests/longevity.py --min_time 1 --max_time 20 + +longevity-test-down: + docker compose -f longevity-tests/docker-compose.yml down generate-certs: generate-root-ca generate-gokms-certs generate-integration-test-certs @@ -170,7 +183,7 @@ generate-etsi-rest-server: # Warning: Depending on your go and development configuration might also clean caches, modules and docker containers from your other projects. clean: + docker system prune -af rm -rf $(BUILD_ARTIFACTS_PATH) rm -rf $(TOOLS_DIR) $(GOCLEAN) - docker system prune -af diff --git a/README.md b/README.md index d01e1542..935c2ca9 100644 --- a/README.md +++ b/README.md @@ -355,6 +355,11 @@ Open the integration test file you want to debug and set your breakpoints in the After all images are build and started wait around 25 seconds before starting to progress through the test. You can switch between stepping through the test and each kms. Stepping through the quantum layer, controller, routing app and akms-simulator is currently not supported. +## Longevity tests + +We have some longevity tests. Simply run `make longevity-test`. +With `python longevity-tests/longevity.py --mode analyze` you can do basic analyzing of the results. + ## Contributing Contributions are welcome! Please follow these guidelines: diff --git a/akms-simulator/Dockerfile b/akms-simulator/Dockerfile index 2bb8f1e8..2286f467 100644 --- a/akms-simulator/Dockerfile +++ b/akms-simulator/Dockerfile @@ -14,6 +14,7 @@ RUN --mount=type=cache,target=/root/go/pkg/mod \ FROM ${GITLAB_PROXY}debian:12-slim AS debian RUN apt-get update && apt-get upgrade -y COPY --from=builder app/artifacts/akms-simulator /usr/bin/akms-simulator +RUN mkdir /logs EXPOSE 4444 ENTRYPOINT ["/usr/bin/akms-simulator"] diff --git a/akms-simulator/akms-simulator.go b/akms-simulator/akms-simulator.go index 050e2afd..dd2d12eb 100644 --- a/akms-simulator/akms-simulator.go +++ b/akms-simulator/akms-simulator.go @@ -12,6 +12,11 @@ import ( "github.com/sirupsen/logrus" ) +const ( + // LogFile is the file where the log is stored. + LogFilePath = "/logs/akms-simulator.log" +) + type LogFile struct { Source string `json:"source"` Body PushKSAKeyRequest `json:"body"` @@ -79,8 +84,8 @@ func main() { func logFileRequest(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodDelete { - if _, err := os.Stat("akms-simulator.log"); err == nil { - err := os.Remove("akms-simulator.log") + if _, err := os.Stat(LogFilePath); err == nil { + err := os.Remove(LogFilePath) if err != nil { logrus.Errorf("Error deleting log file: %s", err) w.WriteHeader(http.StatusInternalServerError) @@ -97,7 +102,7 @@ func logFileRequest(w http.ResponseWriter, r *http.Request) { } logrus.Info("Log file requested") - http.ServeFile(w, r, "akms-simulator.log") + http.ServeFile(w, r, LogFilePath) } func handlePushKsaKey(w http.ResponseWriter, r *http.Request) { @@ -134,7 +139,7 @@ func handlePushKsaKey(w http.ResponseWriter, r *http.Request) { } // Append jsonLogFile to akms-logfile.log - f, err := os.OpenFile("akms-simulator.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) + f, err := os.OpenFile(LogFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { logrus.Errorf("Error opening log file: %s", err) w.WriteHeader(http.StatusInternalServerError) @@ -146,6 +151,12 @@ func handlePushKsaKey(w http.ResponseWriter, r *http.Request) { w.WriteHeader(http.StatusInternalServerError) return } + // Write the newline character + if _, err := f.Write([]byte("\n")); err != nil { + logrus.Errorf("Error writing newline to log file: %s", err) + w.WriteHeader(http.StatusInternalServerError) + return + } w.WriteHeader(http.StatusNoContent) } diff --git a/integration-tests/code/testRestartOfKMSTest/testRestartOfKMS_test.go b/integration-tests/code/testRestartOfKMSTest/testRestartOfKMS_test.go index 838547a2..56d9e55d 100644 --- a/integration-tests/code/testRestartOfKMSTest/testRestartOfKMS_test.go +++ b/integration-tests/code/testRestartOfKMSTest/testRestartOfKMS_test.go @@ -19,7 +19,7 @@ import ( ) // For log file. -type LogFile struct { +type LogFileEntry struct { Source string `json:"source"` Body PushKSAKeyRequest `json:"body"` } @@ -137,7 +137,7 @@ func TestRestartOfKMS(t *testing.T) { //nolint:gocyclo return } - var logFile LogFile + var logFile LogFileEntry 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)) @@ -163,7 +163,7 @@ func TestRestartOfKMS(t *testing.T) { //nolint:gocyclo t.Errorf("Error reading response body: %s", err) return } - var logFile2 LogFile + var logFile2 LogFileEntry err = json.Unmarshal(body, &logFile2) if err != nil { diff --git a/integration-tests/docker-compose-otp.yml b/integration-tests/docker-compose-otp.yml deleted file mode 100644 index 50f043d1..00000000 --- a/integration-tests/docker-compose-otp.yml +++ /dev/null @@ -1,111 +0,0 @@ -services: - kms01: - image: gokms - command: - ["--log", "debug", "--kms_config", "/tmp/kms/config/kms_1_otp.yaml"] - volumes: - - ./config/kms/kms_1_otp.yaml:/tmp/kms/config/kms_1_otp.yaml - - ../artifacts/integration-tests/ssl:/config/ssl - ports: - - "127.0.0.1:7030:7030" - - "127.0.0.1:9696:9696" - - "127.0.0.1:1414:1414" - - kms02: - image: gokms - command: - ["--log", "debug", "--kms_config", "/tmp/kms/config/kms_2_otp.yaml"] - volumes: - - ./config/kms/kms_2_otp.yaml:/tmp/kms/config/kms_2_otp.yaml - - ../artifacts/integration-tests/ssl:/config/ssl - ports: - - "127.0.0.1:7031:7030" - - "127.0.0.1:1415:1414" - - quantumlayer_1: - image: quantumlayer - command: - [ - "--log", - "debug", - "--config", - "/tmp/quantumlayer/config/quantumlayer_1.yaml", - ] - volumes: - - ./config/quantumlayer/quantumlayer_1.yaml:/tmp/quantumlayer/config/quantumlayer_1.yaml - - quantumlayer_2: - image: quantumlayer - command: - [ - "--log", - "debug", - "--config", - "/tmp/quantumlayer/config/quantumlayer_2.yaml", - ] - volumes: - - ./config/quantumlayer/quantumlayer_2.yaml:/tmp/quantumlayer/config/quantumlayer_2.yaml - - akms-simulator_1: - image: akms-simulator - ports: - - "127.0.0.1:4444:4444" - volumes: - - ../artifacts/integration-tests/ssl:/config/ssl - command: - [ - "--ca", - "config/ssl/ca.crt", - "--cert", - "config/ssl/kms/kms2-selfsigned.crt", - "--key", - "config/ssl/kms/kms2-selfsigned.key", - ] - - akms-simulator_2: - image: akms-simulator - volumes: - - ../artifacts/integration-tests/ssl:/config/ssl - ports: - - "127.0.0.1:4445:4444" - command: - [ - "--ca", - "config/ssl/ca.crt", - "--cert", - "config/ssl/kms/kms1-selfsigned.crt", - "--key", - "config/ssl/kms/kms1-selfsigned.key", - ] - - 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: - - 0.0.0.0:55055:55055 - - 127.0.0.1:8080:8080 - - 127.0.0.1:40000:40000 - environment: - GOSDN_ADMIN_PASSWORD: TestPassword - - 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/integration-tests/docker-compose.override.otp.yml b/integration-tests/docker-compose.override.otp.yml new file mode 100644 index 00000000..740031a6 --- /dev/null +++ b/integration-tests/docker-compose.override.otp.yml @@ -0,0 +1,16 @@ +services: + kms01: + image: gokms + command: + ["--log", "debug", "--kms_config", "/tmp/kms/config/kms_1_otp.yaml"] + volumes: + - ./config/kms/kms_1_otp.yaml:/tmp/kms/config/kms_1_otp.yaml + - ../artifacts/integration-tests/ssl:/config/ssl + + kms02: + image: gokms + command: + ["--log", "debug", "--kms_config", "/tmp/kms/config/kms_2_otp.yaml"] + volumes: + - ./config/kms/kms_2_otp.yaml:/tmp/kms/config/kms_2_otp.yaml + - ../artifacts/integration-tests/ssl:/config/ssl diff --git a/longevity-tests/docker-compose.yml b/longevity-tests/docker-compose.yml new file mode 100644 index 00000000..6357e3dc --- /dev/null +++ b/longevity-tests/docker-compose.yml @@ -0,0 +1,136 @@ +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 + ports: + - "127.0.0.1:4444:4444" + volumes: + - ./akms1-logs:/logs + + akms-receiver02: + image: akms-simulator + ports: + - "127.0.0.1:4445:4444" + volumes: + - ./akms2-logs:/logs + + 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/longevity-tests/longevity.py b/longevity-tests/longevity.py new file mode 100644 index 00000000..d2fa36a2 --- /dev/null +++ b/longevity-tests/longevity.py @@ -0,0 +1,115 @@ +import http.client +import json +import time +import argparse +import random + +def sleepRandomTime(min_time: int, max_time: int): + time.sleep(random.randint(min_time, max_time)) + + +def requestMode(baseURL: str, min_time: int, max_time: int): + endpoint = "/api/v1/keys/ksa_key_req" + request_id = 0 + while True: + request_id += 1 + print(f"requestId: {request_id}") + data = { + "receiving_CKMS_ID": "968fd594-b0e7-41f0-ba4b-de259047a933", + "request_ID": str(request_id), + "key_properties": { + "number": 1, + "key_length": 256, + "timeout": 20, + "TTL": 24 + } + } + + headers = { + "Content-Type": "application/json" + } + + # Create a connection + conn = http.client.HTTPConnection(baseURL) + # Convert data to JSON + json_data = json.dumps(data) + # Make the POST request + conn.request("POST", endpoint, body=json_data, headers=headers) + + # Check the return code + response = conn.getresponse() + if response.status != 204: + print(f"Request failed with status code {response.status}") + print(response.read().decode()) + + # Close the connection + conn.close() + + sleepRandomTime(min_time, max_time) + + +def readFile(fileURL: str): + with open(fileURL, 'r') as file: + lines = file.readlines() + parsed_lines = [] + for line in lines: + data = json.loads(line.strip()) + parsed_line = { + "source": data["source"], + "request_ID": data["body"]["request_ID"], + "process_ID": data["body"]["process_ID"], + "ksa_keys": data["body"]["ksa_keys"] + } + parsed_lines.append(parsed_line) + + return parsed_lines + + +def analyzeMode(fileURLs: list): + data = [] + for fileURL in fileURLs: + fileData = readFile(fileURL) + data.append(fileData) + + for i, log in enumerate(data): + if len(log) == len(data[0]): + print("Logs are the same length!") + + +def main(): + # Parse the command line arguments --mode, --min_time, --max_time and --base_url + parser = argparse.ArgumentParser(description="Longevity test script") + parser.add_argument("--mode", type=str, required=False, + help="Mode of operation. Can be 'request' or 'analyze'.") + parser.add_argument("--min_time", type=int, + required=False, help="Minimum time in seconds") + parser.add_argument("--max_time", type=int, + required=False, help="Maximum time in seconds") + parser.add_argument("--base_url", type=str, required=False, + help="Base URL for the requests") + args = parser.parse_args() + + mode = args.mode + min_time = args.min_time + max_time = args.max_time + base_url = args.base_url + + # Set default values + if mode is None: + mode = "request" + if min_time is None: + min_time = 10 + if max_time is None: + max_time = 240 + if base_url is None: + base_url = "127.0.0.1:9696" + + if mode == "request": + print("Running in request mode") + requestMode(base_url, min_time, max_time) + elif mode == "analyze": + print("Running in analyze mode") + analyzeMode(["longevity-tests/akms1-logs/akms-simulator.log", "longevity-tests/akms2-logs/akms-simulator.log"]) + +if __name__ == "__main__": + main() diff --git a/longevity-tests/run-curl.sh b/longevity-tests/run-curl.sh new file mode 100755 index 00000000..648132f7 --- /dev/null +++ b/longevity-tests/run-curl.sh @@ -0,0 +1,22 @@ +#!/bin/bash + +url="https://${kms1AkmsURL}/api/v1/keys/ksa_key_req" + +# Loop for ever and increase a requestId variable +requestId=0 +while true; do + requestId=$((requestId+1)) + echo "requestId: $requestId" + + curl -X POST -H "Content-Type: application/json" -d '{ + "receiving_CKMS_ID": "968fd594-b0e7-41f0-ba4b-de259047a933", + "request_ID": "${requestId}", + "key_properties": { + "number": 1, + "key_length": 256, + "timeout": 20, + "TTL": 24 + } + }' 'http://127.0.0.1:9696/api/v1/keys/ksa_key_req' + sleep 1 +done -- GitLab