diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index cd96c21d9c3159fc769342210740624e6090d1d2..04de559d278e5bbdabda1a740fabadb3ac6ab59f 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 ba1c1ed94b1a2a741482af5f1ec7528c9d34296c..4ff652cf4d6a72f1063869b602ca50d598149c94 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 70f8fa1d662f4a79adb6470d5ad123a139cbcbc1..cbc246efc7304673d8adf749676b245696c2d0f5 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 4a96cdf360b7fd2d0ecc625c5c17846b79ce5283..69fba2afa69a059641134bc51c638061e551d212 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 d01e1542c3cbcb7e59083e7177c1fc0b9ce1b4a6..935c2ca942b3f7db712246491c1254e9bbabd270 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 2bb8f1e8248007fe17bdee3c21af74939f65fce7..2286f46717de61edbae3b2c81f9f24aeb3ca3506 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 050e2afde84891bedcacba891fa5c0e57376553c..dd2d12eb70f87e5b4296f07086aebd6f2f46a4de 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 838547a243364b16fe5fae480d4bdbbc231cd166..56d9e55dc8295ee410c31ea86fd74c125978d3f0 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 50f043d1f732a8fb7fc8b8e4e18b1fa05021d472..0000000000000000000000000000000000000000 --- 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 0000000000000000000000000000000000000000..740031a6a21bcc3009aa3b7aed0fff765bcb48c4 --- /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 0000000000000000000000000000000000000000..6357e3dcb330fe8eb37a3aac77f8168893af51b2 --- /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 0000000000000000000000000000000000000000..d2fa36a21aff770bf6a0f2b62b56840a125f4c62 --- /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 0000000000000000000000000000000000000000..648132f7a1d8641ca97aa9ca02ffec9cd799fea2 --- /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