From a071d6bea71df7957eec9d31748d6eedb5870ba0 Mon Sep 17 00:00:00 2001 From: Default Date: Fri, 13 Jun 2025 08:28:32 +0200 Subject: [PATCH 01/16] Fix build_docker_images.yml. - For users, which use a name which has uppercase name. --- .github/workflows/build_docker_images.yml | 26 ++++++++++++++--------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/.github/workflows/build_docker_images.yml b/.github/workflows/build_docker_images.yml index a6eba933..44a6865f 100644 --- a/.github/workflows/build_docker_images.yml +++ b/.github/workflows/build_docker_images.yml @@ -15,8 +15,9 @@ name: Build and push base docker images on: push: paths: - - 'data/dockerfiles/Dockerfile.*' - - 'requirements*.txt' + - 'data/dockerfiles/Dockerfile.*' + - '.github/workflows/build_docker_images.yml' + - 'requirements*.txt' workflow_dispatch: jobs: @@ -36,28 +37,33 @@ jobs: username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} + # Some accounts did not use a lowercase repository owner, so we need to ensure + # that the repository owner is always in lowercase to be able to build the images. + - name: Set lowercase GitHub owner + run: echo "REPO_OWNER_LC=${GITHUB_REPOSITORY_OWNER,,}" >> $GITHUB_ENV + - name: Build and push base Docker image run: | docker buildx build \ - --tag ghcr.io/${{ github.repository_owner }}/cmp-test-base:latest \ + --tag ghcr.io/${REPO_OWNER_LC}/cmp-test-base:latest \ --push \ -f data/dockerfiles/Dockerfile.base . - name: Build and push dev Docker image run: | docker buildx build \ - --tag ghcr.io/${{ github.repository_owner }}/cmp-test-dev:latest \ - --build-arg BASE_IMAGE=ghcr.io/${{ github.repository_owner }}/cmp-test-base:latest \ + --tag ghcr.io/${REPO_OWNER_LC}/cmp-test-dev:latest \ + --build-arg BASE_IMAGE=ghcr.io/${REPO_OWNER_LC}/cmp-test-base:latest \ --push \ -f data/dockerfiles/Dockerfile.dev . - name: Build and push the production test suite Docker image - # This one is meant to be directly invoked by end-users who don't want to get into the details - # of how the test suite works, they just want to run it to test their CA. For their convenience, - # we give it a short name, to be invoked as `docker run --rm -it ghcr.io/siemens/cmp-test` + # This one is meant to be directly invoked by end-users who don't want to get into the details + # of how the test suite works, they just want to run it to test their CA. For their convenience, + # we give it a short name, to be invoked as `docker run --rm -it ghcr.io/siemens/cmp-test` run: | docker buildx build \ - --tag ghcr.io/${{ github.repository_owner }}/cmp-test:latest \ - --build-arg BASE_IMAGE=ghcr.io/${{ github.repository_owner }}/cmp-test-base:latest \ + --tag ghcr.io/${REPO_OWNER_LC}/cmp-test:latest \ + --build-arg BASE_IMAGE=ghcr.io/${REPO_OWNER_LC}/cmp-test-base:latest \ --push \ -f data/dockerfiles/Dockerfile.tests . From 839f52c5d315942ca3a49fa4a7231973c9f392d8 Mon Sep 17 00:00:00 2001 From: Default Date: Fri, 13 Jun 2025 08:33:08 +0200 Subject: [PATCH 02/16] Update Dockerfile.base for StatefulSignature keys. - To use my forked repository. --- data/dockerfiles/Dockerfile.base | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/dockerfiles/Dockerfile.base b/data/dockerfiles/Dockerfile.base index d5cd07c0..88491aba 100644 --- a/data/dockerfiles/Dockerfile.base +++ b/data/dockerfiles/Dockerfile.base @@ -17,8 +17,8 @@ RUN pip3 install --upgrade pip && \ pip3 install -r /app/requirements.txt # Build and install liboqs-python -RUN git clone --depth=1 https://github.com/open-quantum-safe/liboqs-python && \ - pip3 install ./liboqs-python && \ +RUN git clone --depth=1 https://github.com/Guiliano99/liboqs-python-stateful-sig && \ + pip3 install ./liboqs-python-stateful-sig && \ python3 -c "import oqs" # Trigger the build of liboqs, by importing it # Remove unnecessary packages after we're done From 8ffbff3ae8fa4d8e31d3534d80a4a925cdb0dd4d Mon Sep 17 00:00:00 2001 From: Default Date: Fri, 13 Jun 2025 08:43:29 +0200 Subject: [PATCH 03/16] Update check_quality.yml. --- .github/workflows/check_quality.yml | 125 +++++++++++++++++----------- 1 file changed, 78 insertions(+), 47 deletions(-) diff --git a/.github/workflows/check_quality.yml b/.github/workflows/check_quality.yml index 5f16abbb..e3a46080 100644 --- a/.github/workflows/check_quality.yml +++ b/.github/workflows/check_quality.yml @@ -13,80 +13,106 @@ on: - main workflow_dispatch: +env: + REPO_OWNER: ${{ github.repository_owner }} + IMAGE_BASE_RAW: ghcr.io/${{ github.repository_owner }}/cmp-test-dev:latest + jobs: # Stage 1: fast and basic checks, we run them in parallel to provide more feedback to the contributor at once, # instead of running them sequentially and giving feedback one piece at a time, requiring more iterations. + ensure_repo_lowercase: + runs-on: ubuntu-22.04 + steps: + - name: Check if image base is lowercase + run: | + IMAGE_LC=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') + if [ "${IMAGE_BASE_RAW}" != "${IMAGE_LC}" ]; then + echo "Repository name or image path must be lowercase. Found: '${IMAGE_BASE_RAW}'" + exit 1 + fi + ruff_lint: + needs: ensure_repo_lowercase runs-on: ubuntu-22.04 - container: - image: ghcr.io/${{ github.repository_owner }}/cmp-test-dev:latest steps: - name: Checkout code uses: actions/checkout@v4 - - name: Code style - run: ruff check + - name: Code style (ruff) + run: | + IMAGE=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') + docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" ruff check license_check: + needs: ensure_repo_lowercase runs-on: ubuntu-22.04 - container: - image: ghcr.io/${{ github.repository_owner }}/cmp-test-dev:latest steps: - name: Checkout code uses: actions/checkout@v4 - - name: License check - run: reuse lint + + - name: License check (reuse) + run: | + IMAGE=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') + docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" reuse lint + rf_style_check: + needs: ensure_repo_lowercase runs-on: ubuntu-22.04 - container: - image: ghcr.io/${{ github.repository_owner }}/cmp-test-dev:latest + continue-on-error: true steps: - name: Checkout code uses: actions/checkout@v4 - - name: RobotFramework style check - run: robocop check --ignore VAR04 - # We haven't settled on a style for RobotFramework yet, enforce check when consensus is reached - continue-on-error: true + + - name: RobotFramework style check (robocop) + run: | + IMAGE=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') + docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" robocop check --ignore VAR04 + spelling_check: + needs: ensure_repo_lowercase runs-on: ubuntu-22.04 - container: - image: ghcr.io/${{ github.repository_owner }}/cmp-test-dev:latest steps: - name: Checkout code uses: actions/checkout@v4 - - name: Spelling checker - run: codespell . --check-filenames --skip *.html,*.pem,*.xml,*venv*,*fips/*.py,*/announcement.py + + - name: Spelling checker (codespell) + run: | + IMAGE=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') + docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" \ + codespell . --check-filenames --skip "*.html,*.pem,*.xml,*venv*,*fips/*.py,*/announcement.py" + dependency_check: - # See if newer versions of our Python dependencies are available. This does - # not enforce anything, and only has an informational character. + needs: ensure_repo_lowercase runs-on: ubuntu-22.04 continue-on-error: true - container: - image: ghcr.io/${{ github.repository_owner }}/cmp-test-dev:latest steps: - name: Check for outdated dependencies run: | - echo "Checking for outdated packages..." - OUTDATED=$(pip list --outdated --format=columns) - if [ -z "$OUTDATED" ]; then - echo "All packages are up to date!" - exit 0 - else - echo "Outdated packages detected, think about it:" - echo "$OUTDATED" - exit 1 - fi + IMAGE=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') + docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" bash -c ' + echo "Checking for outdated packages..." + OUTDATED=$(pip list --outdated --format=columns) + if [ -z "$OUTDATED" ]; then + echo "All packages are up to date!" + exit 0 + else + echo "Outdated packages detected:" + echo "$OUTDATED" + exit 1 + fi' + version_check: + needs: ensure_repo_lowercase runs-on: ubuntu-22.04 steps: - name: Checkout code uses: actions/checkout@v4 - - name: Ensure version is referenced in CHANGELOG.md + - name: Ensure version is in CHANGELOG.md run: | VERSION=$(cat VERSION) if ! grep -E "^# $VERSION" CHANGELOG.md; then @@ -100,36 +126,41 @@ jobs: pylint: needs: [ruff_lint, license_check, rf_style_check, spelling_check] runs-on: ubuntu-22.04 - container: - image: ghcr.io/${{ github.repository_owner }}/cmp-test-dev:latest steps: - name: Checkout code uses: actions/checkout@v4 + - name: Pylint check - run: pylint --fail-under=9.4 resources + run: | + IMAGE=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') + docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" pylint --fail-under=9.4 resources + unit_test: needs: [ruff_lint, license_check, rf_style_check, spelling_check] runs-on: ubuntu-22.04 - container: - image: ghcr.io/${{ github.repository_owner }}/cmp-test-dev:latest env: OQS_INSTALL_PATH: "/root/_oqs" steps: - name: Checkout code uses: actions/checkout@v4 - - name: Unit tests - run: python3 -m unittest discover -s unit_tests + + - name: Run unit tests + run: | + IMAGE=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') + docker run --rm -v "$PWD:/workspace" -w /workspace -e OQS_INSTALL_PATH=/root/_oqs "$IMAGE" \ + python3 -m unittest discover -s unit_tests + type_check: + needs: ensure_repo_lowercase runs-on: ubuntu-22.04 - container: - image: ghcr.io/${{ github.repository_owner }}/cmp-test-dev:latest - + continue-on-error: true steps: - name: Checkout code uses: actions/checkout@v4 - - name: Pyright check - run: pyright - # not enforced yet, but it is still executed to provide some info - continue-on-error: true + + - name: Pyright type check + run: | + IMAGE=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') + docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" pyright From bb266423e6a36029c2cc31342a031e500270fbce Mon Sep 17 00:00:00 2001 From: Default Date: Fri, 13 Jun 2025 08:43:29 +0200 Subject: [PATCH 04/16] Update check_quality.yml. --- .github/workflows/check_quality.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check_quality.yml b/.github/workflows/check_quality.yml index e3a46080..2dd24426 100644 --- a/.github/workflows/check_quality.yml +++ b/.github/workflows/check_quality.yml @@ -139,7 +139,7 @@ jobs: unit_test: needs: [ruff_lint, license_check, rf_style_check, spelling_check] runs-on: ubuntu-22.04 - env: + env: OQS_INSTALL_PATH: "/root/_oqs" steps: - name: Checkout code From f8aab1cc8a7013c56cb3588cd509a440f7bdfc9a Mon Sep 17 00:00:00 2001 From: Default Date: Fri, 13 Jun 2025 10:31:07 +0200 Subject: [PATCH 05/16] Update check_quality.yml. - To use the lower case name, for the docker container. --- .github/workflows/check_quality.yml | 128 +++++++++++----------------- 1 file changed, 52 insertions(+), 76 deletions(-) diff --git a/.github/workflows/check_quality.yml b/.github/workflows/check_quality.yml index 2dd24426..e012b5fe 100644 --- a/.github/workflows/check_quality.yml +++ b/.github/workflows/check_quality.yml @@ -6,92 +6,78 @@ name: Check code quality on: push: - branches: - - main + branches: [main] pull_request: - branches: - - main + branches: [main] workflow_dispatch: -env: - REPO_OWNER: ${{ github.repository_owner }} - IMAGE_BASE_RAW: ghcr.io/${{ github.repository_owner }}/cmp-test-dev:latest - jobs: - # Stage 1: fast and basic checks, we run them in parallel to provide more feedback to the contributor at once, - # instead of running them sequentially and giving feedback one piece at a time, requiring more iterations. - ensure_repo_lowercase: + prepare_env: runs-on: ubuntu-22.04 + outputs: + image_lc: ${{ steps.setenv.outputs.image_lc }} steps: - - name: Check if image base is lowercase + - name: Set lowercase image name + id: setenv run: | - IMAGE_LC=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') - if [ "${IMAGE_BASE_RAW}" != "${IMAGE_LC}" ]; then - echo "Repository name or image path must be lowercase. Found: '${IMAGE_BASE_RAW}'" - exit 1 - fi + OWNER_LC=$(echo "${{ github.repository_owner }}" | tr '[:upper:]' '[:lower:]') + IMAGE_LC="ghcr.io/${OWNER_LC}/cmp-test-dev:latest" + echo "image_lc=$IMAGE_LC" >> $GITHUB_OUTPUT ruff_lint: - needs: ensure_repo_lowercase + needs: prepare_env runs-on: ubuntu-22.04 + env: + IMAGE: ${{ needs.prepare_env.outputs.image_lc }} steps: - - name: Checkout code - uses: actions/checkout@v4 - + - uses: actions/checkout@v4 - name: Code style (ruff) - run: | - IMAGE=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') - docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" ruff check + run: docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" ruff check license_check: - needs: ensure_repo_lowercase + needs: prepare_env runs-on: ubuntu-22.04 + env: + IMAGE: ${{ needs.prepare_env.outputs.image_lc }} steps: - - name: Checkout code - uses: actions/checkout@v4 - + - uses: actions/checkout@v4 - name: License check (reuse) - run: | - IMAGE=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') - docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" reuse lint - + run: docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" reuse lint rf_style_check: - needs: ensure_repo_lowercase + needs: prepare_env runs-on: ubuntu-22.04 continue-on-error: true + env: + IMAGE: ${{ needs.prepare_env.outputs.image_lc }} steps: - - name: Checkout code - uses: actions/checkout@v4 - + - uses: actions/checkout@v4 - name: RobotFramework style check (robocop) - run: | - IMAGE=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') - docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" robocop check --ignore VAR04 - + run: docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" robocop check --ignore VAR04 spelling_check: - needs: ensure_repo_lowercase + needs: prepare_env runs-on: ubuntu-22.04 + env: + IMAGE: ${{ needs.prepare_env.outputs.image_lc }} steps: - - name: Checkout code - uses: actions/checkout@v4 - + - uses: actions/checkout@v4 - name: Spelling checker (codespell) run: | - IMAGE=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" \ codespell . --check-filenames --skip "*.html,*.pem,*.xml,*venv*,*fips/*.py,*/announcement.py" - dependency_check: - needs: ensure_repo_lowercase + # See if newer versions of our Python dependencies are available. This does + # not enforce anything, and only has an informational character. + needs: prepare_env runs-on: ubuntu-22.04 continue-on-error: true + env: + IMAGE: ${{ needs.prepare_env.outputs.image_lc }} steps: - name: Check for outdated dependencies run: | - IMAGE=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" bash -c ' echo "Checking for outdated packages..." OUTDATED=$(pip list --outdated --format=columns) @@ -104,14 +90,11 @@ jobs: exit 1 fi' - version_check: - needs: ensure_repo_lowercase + needs: prepare_env runs-on: ubuntu-22.04 steps: - - name: Checkout code - uses: actions/checkout@v4 - + - uses: actions/checkout@v4 - name: Ensure version is in CHANGELOG.md run: | VERSION=$(cat VERSION) @@ -119,48 +102,41 @@ jobs: echo "Error: CHANGELOG.md does not contain an entry for version $VERSION." exit 1 fi - # ---------------------------------------------------------------------------- # Stage 2: these checks are more expensive and do more with the code, e.g., attempt to import dependencies, # execute some logic, etc. pylint: - needs: [ruff_lint, license_check, rf_style_check, spelling_check] + # needs must include prepare_env, as it is used to set the image name. + needs: [prepare_env, ruff_lint, license_check, rf_style_check, spelling_check] runs-on: ubuntu-22.04 + env: + IMAGE: ${{ needs.prepare_env.outputs.image_lc }} steps: - - name: Checkout code - uses: actions/checkout@v4 - + - uses: actions/checkout@v4 - name: Pylint check - run: | - IMAGE=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') - docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" pylint --fail-under=9.4 resources - + run: docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" pylint --fail-under=9.4 resources unit_test: - needs: [ruff_lint, license_check, rf_style_check, spelling_check] + # needs must include prepare_env, as it is used to set the image name. + needs: [prepare_env, ruff_lint, license_check, rf_style_check, spelling_check] runs-on: ubuntu-22.04 env: - OQS_INSTALL_PATH: "/root/_oqs" + IMAGE: ${{ needs.prepare_env.outputs.image_lc }} steps: - - name: Checkout code - uses: actions/checkout@v4 - + - uses: actions/checkout@v4 - name: Run unit tests run: | - IMAGE=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') docker run --rm -v "$PWD:/workspace" -w /workspace -e OQS_INSTALL_PATH=/root/_oqs "$IMAGE" \ python3 -m unittest discover -s unit_tests - type_check: - needs: ensure_repo_lowercase + needs: prepare_env runs-on: ubuntu-22.04 + # not enforced yet, but it is still executed to provide some info. continue-on-error: true + env: + IMAGE: ${{ needs.prepare_env.outputs.image_lc }} steps: - - name: Checkout code - uses: actions/checkout@v4 - + - uses: actions/checkout@v4 - name: Pyright type check - run: | - IMAGE=$(echo "${IMAGE_BASE_RAW}" | tr '[:upper:]' '[:lower:]') - docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" pyright + run: docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" pyright From 725ce1619fb9c8cb00f19acf7ac36eaa436d7230 Mon Sep 17 00:00:00 2001 From: Default Date: Mon, 30 Jun 2025 21:38:46 +0200 Subject: [PATCH 06/16] Remove version check for liboqs sign with context. --- pq_logic/keys/sig_keys.py | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/pq_logic/keys/sig_keys.py b/pq_logic/keys/sig_keys.py index af471179..54be3db2 100644 --- a/pq_logic/keys/sig_keys.py +++ b/pq_logic/keys/sig_keys.py @@ -48,14 +48,6 @@ ML_DSA_NAMES = ["ml-dsa-44", "ml-dsa-65", "ml-dsa-87"] -def _extract_minor_patch() -> bool: - version = oqs.oqs_python_version() # type: ignore - parts = version.split(".") - minor = int(parts[1]) # Middle number - patch = int(parts[2]) # Last number - return float(f"{minor}.{patch}") == 12.0 - - class MLDSAPublicKey(PQSignaturePublicKey): """Represent an ML-DSA public key.""" @@ -99,8 +91,7 @@ def verify( hash_alg = self.check_hash_alg(hash_alg=hash_alg, allow_failure=False) if hash_alg is None and not is_prehashed and oqs is not None: - if _extract_minor_patch(): - return super().verify(signature=signature, data=data, ctx=ctx) + return super().verify(signature=signature, data=data, ctx=ctx) ml_ = fips204.ML_DSA(self.name) if hash_alg is None: @@ -349,8 +340,7 @@ def sign( hash_alg = self.check_hash_alg(hash_alg) if hash_alg is None and not is_prehashed and oqs is not None: - if _extract_minor_patch(): - return super().sign(data=data, hash_alg=hash_alg, ctx=ctx) + return super().sign(data=data, hash_alg=hash_alg, ctx=ctx) if hash_alg is None: ml_ = fips204.ML_DSA(self.name) From a29fdb315ef6ec0701ae97a26d3cb2a4cf89b9e7 Mon Sep 17 00:00:00 2001 From: Guiliano Date: Mon, 11 Aug 2025 18:41:53 +0200 Subject: [PATCH 07/16] Update Dockerfile.base to use python-liboqs again. --- data/dockerfiles/Dockerfile.base | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/dockerfiles/Dockerfile.base b/data/dockerfiles/Dockerfile.base index 88491aba..8d820e2d 100644 --- a/data/dockerfiles/Dockerfile.base +++ b/data/dockerfiles/Dockerfile.base @@ -17,8 +17,8 @@ RUN pip3 install --upgrade pip && \ pip3 install -r /app/requirements.txt # Build and install liboqs-python -RUN git clone --depth=1 https://github.com/Guiliano99/liboqs-python-stateful-sig && \ - pip3 install ./liboqs-python-stateful-sig && \ +RUN git clone --depth=1 https://github.com/open-quantum-safe/liboqs && \ + pip3 install ./liboqs-python && \ python3 -c "import oqs" # Trigger the build of liboqs, by importing it # Remove unnecessary packages after we're done From 5a0bc63b4a693279d84f9f64fb1e6c94306d318c Mon Sep 17 00:00:00 2001 From: Guiliano Date: Mon, 11 Aug 2025 18:55:55 +0200 Subject: [PATCH 08/16] Add licenses/Run ruff --- REUSE.toml | 4 +++- client_tests/README.md | 37 +++++++++++++++++------------- client_tests/cmp_client.py | 34 ++++++++++++++++----------- client_tests/cmp_tests_jinja.robot | 4 ++++ 4 files changed, 48 insertions(+), 31 deletions(-) diff --git a/REUSE.toml b/REUSE.toml index 2ac0d4cc..928e6150 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -10,7 +10,9 @@ SPDX-License-Identifier = "Apache-2.0" # these are config files or sample payloads which may be in formats that cannot # be annotated, hence we mention the relevant information here [[annotations]] -path = ["config/cert/**", "data/**", "unit_tests/**", "scripts/**", "pyrightconfig.json", "VERSION"] +path = ["config/cert/**", "data/**", "unit_tests/**", + "scripts/**", "pyrightconfig.json", "VERSION", + "client_tests/certs/**"] precedence = "override" SPDX-FileCopyrightText = "Copyright 2024 Siemens AG" SPDX-License-Identifier = "Apache-2.0" \ No newline at end of file diff --git a/client_tests/README.md b/client_tests/README.md index faa54b6a..733ba32e 100644 --- a/client_tests/README.md +++ b/client_tests/README.md @@ -1,3 +1,9 @@ + + This folder contains an experimental draft for test cases of client-side CMP implementations. @@ -31,19 +37,18 @@ CMP implementations. ${REVOCATION_REQUEST} rr ``` 2. Define all available CLI commands for your cmp client in "cmp_client.py" using jinja, example of openssl: - ```python - openssl = """ - openssl cmp - -cmd {{ cmd }} - -server {{ server }} - -subject {{ subject }} - -secret {{ secret }} - -ref {{ ref | default('NULL-DN') }} - {% if recipient %}-recipient {{ recipient }}{% endif %} - {% if csr %}-csr {{ csr }}{% endif %} - {% if newkey %}-newkey {{ newkey }}{% endif %} - {% if certout %}-certout {{ certout }}{% endif %} - {% if unprotected_requests %}-unprotected_requests{% endif %} - """ - - ``` +```python +openssl = """ + openssl cmp + -cmd {{ cmd }} + -server {{ server }} + -subject {{ subject }} + -secret {{ secret }} + -ref {{ ref | default('NULL-DN') }} + {% if recipient %}-recipient {{ recipient }}{% endif %} + {% if csr %}-csr {{ csr }}{% endif %} + {% if newkey %}-newkey {{ newkey }}{% endif %} + {% if certout %}-certout {{ certout }}{% endif %} + {% if unprotected_requests %}-unprotected_requests{% endif %} + """ +``` diff --git a/client_tests/cmp_client.py b/client_tests/cmp_client.py index 5aaaaa17..e77251b8 100644 --- a/client_tests/cmp_client.py +++ b/client_tests/cmp_client.py @@ -1,7 +1,12 @@ +# SPDX-FileCopyrightText: Copyright 2025 Siemens AG +# +# SPDX-License-Identifier: Apache-2.0 + +"""CMP Client Command Generation Module""" + +from jinja2 import Template from robot.api.deco import keyword -from jinja2 import Template, Environment, FileSystemLoader -import os -import subprocess + # Jinja2 templates for CMP CLI commands, define your template here # This translates the tests in cmp_tests_jinja.robot to the actual commands that your CMP client will execute. openssl = """ @@ -26,10 +31,9 @@ --secret "{{ secret }}" {% if csr %}--csr {{ csr }}{% endif %} {% if newkey %}--newkey {{ newkey }}{% endif %} - {% if certout %}--certout {{ certout }}{% endif %} - - """ - + {% if certout %}--certout {{ certout }}{% endif %} +""" # noqa: W291 Trailing whitespace + embedded_cmp = """ ./build/embedded_cmp {% if cmd == "ir" %}-i{% endif %} @@ -37,27 +41,29 @@ {% if cmd == "kur" %}-k{% endif %} """ + @keyword(name="Get CMP Command") -def get_cmp_command(client: str = "openssl", **kwargs) -> list: - """Constructs a CMP command based on the client and keyword arguments. +def get_cmp_command(client: str = "openssl", **kwargs) -> list: # noqa: D417 undocumented params + """Construct a CMP command based on the client and keyword arguments. Arguments: - ---------- + --------- - `client`: The CMP client to use (e.g. "openssl"). - `**kwargs`: Keyword arguments like cmd, server, ref, subject, etc. Returns: - -------- + ------- - List of command-line arguments suitable for use with Run Process Example: - -------- + ------- | ${args}= | Get CMP Command | openssl | cmd=ir | server=http://localhost:5000 | ... | + """ try: template = Template(globals()[client]) except KeyError: raise ValueError(f"Unsupported CMP client: {client}") - + rendered = template.render(**kwargs) - return rendered.strip().split() \ No newline at end of file + return rendered.strip().split() diff --git a/client_tests/cmp_tests_jinja.robot b/client_tests/cmp_tests_jinja.robot index 1f2a54b6..82e778a4 100644 --- a/client_tests/cmp_tests_jinja.robot +++ b/client_tests/cmp_tests_jinja.robot @@ -1,3 +1,7 @@ +# SPDX-FileCopyrightText: Copyright 2025 Siemens AG # robocop: off=COM04 +# +# SPDX-License-Identifier: Apache-2.0 + *** Settings *** Documentation Minimal CMP tests. Library Process From 3bcc6cf410bcd8396549880083b522aebcacac7c Mon Sep 17 00:00:00 2001 From: Guiliano Date: Tue, 12 Aug 2025 19:57:36 +0200 Subject: [PATCH 09/16] Fix Dockerfile.base liboqs-python name. --- data/dockerfiles/Dockerfile.base | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/dockerfiles/Dockerfile.base b/data/dockerfiles/Dockerfile.base index 8d820e2d..d5cd07c0 100644 --- a/data/dockerfiles/Dockerfile.base +++ b/data/dockerfiles/Dockerfile.base @@ -17,7 +17,7 @@ RUN pip3 install --upgrade pip && \ pip3 install -r /app/requirements.txt # Build and install liboqs-python -RUN git clone --depth=1 https://github.com/open-quantum-safe/liboqs && \ +RUN git clone --depth=1 https://github.com/open-quantum-safe/liboqs-python && \ pip3 install ./liboqs-python && \ python3 -c "import oqs" # Trigger the build of liboqs, by importing it From 044c9441fb538bf9efcee0ef692622bd9a05a98c Mon Sep 17 00:00:00 2001 From: Guiliano99 Date: Wed, 13 Aug 2025 09:57:56 +0200 Subject: [PATCH 10/16] Update dep. cryptography==45.0.6 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index c7741efa..122e4def 100644 --- a/requirements.txt +++ b/requirements.txt @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 -cryptography==45.0.5 +cryptography==45.0.6 pyasn1==0.6.1 pyasn1-alt-modules==0.4.6 robotframework==7.3 From 1e19e8f25efbc708b559e4ecf29e0abf0046ebd9 Mon Sep 17 00:00:00 2001 From: Guiliano99 Date: Wed, 13 Aug 2025 10:03:48 +0200 Subject: [PATCH 11/16] Update dep. jinja2==3.1.6. - Fixed CVE. --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 122e4def..0c6ae2fa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,4 +13,4 @@ pycryptodome==3.23.0 Flask==3.1.1 tinyec==0.4.0 # relevant for the CMP client tests. -jinja2==3.1.4 \ No newline at end of file +jinja2==3.1.6 \ No newline at end of file From 332f5153db67ddafcd637de9027501207cd58693 Mon Sep 17 00:00:00 2001 From: Guiliano99 Date: Wed, 13 Aug 2025 10:04:08 +0200 Subject: [PATCH 12/16] Remove spaces in client tests. --- client_tests/cmp_tests_jinja.robot | 7 ------- 1 file changed, 7 deletions(-) diff --git a/client_tests/cmp_tests_jinja.robot b/client_tests/cmp_tests_jinja.robot index 82e778a4..ba01c931 100644 --- a/client_tests/cmp_tests_jinja.robot +++ b/client_tests/cmp_tests_jinja.robot @@ -48,7 +48,6 @@ IR 01 - Valid IR CMP Request Should Pass ... The OpenSSL client output should not contain any errors, ... and a certificate should be written to the specified path. [Tags] ir valid positive - ${args}= Get CMP Command ... ${CMP_CLIENT} ... cmd=${INITIATION_REQUEST} @@ -79,9 +78,6 @@ IR 02 - IR Request With Wrong Secret Should Fail ... The OpenSSL client output should indicate a failure due to authentication error ... and include the keyword `error`. [Tags] ir negative secret - - - ${args}= Get CMP Command ... ${CMP_CLIENT} ... cmd=${INITIATION_REQUEST} @@ -110,8 +106,6 @@ P10CR 01 - P10CR Unprotected Request Should Fail ... ... The OpenSSL client should log an error related to missing request protection. [Tags] p10cr negative unprotected - - ${args}= Get CMP Command ... ${CMP_CLIENT} ... cmd=${CERTIFICATION_REQUEST} @@ -164,7 +158,6 @@ P10CR 03 - Valid P10CR With CSR Should Pass ... This test uses a signed CSR (`csr_p10cr-client-3.pem`) and a shared secret ... to authenticate the request. The subject in the CSR matches the subject in the CMP header. [Tags] p10cr positive validation - ${args}= Get CMP Command ... ${CMP_CLIENT} ... cmd=${CERTIFICATION_REQUEST} From aa5b206b5eff09bdfb772861c7fe30f477d2bfad Mon Sep 17 00:00:00 2001 From: Guiliano99 Date: Sun, 2 Nov 2025 08:01:02 +0100 Subject: [PATCH 13/16] Update ruff min. version to 0.14.3. --- requirements-dev.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index e697a692..5045a146 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -5,7 +5,7 @@ safety>= 3.3.1, < 4.0.0 pylint>= 4.0.2, < 5.0.0 black>= 25.0.0, < 26.0.0 -ruff>= 0.12.12, < 1.0.0 +ruff>= 0.14.3, < 1.0.0 robotframework-robocop==6.9.2 robotframework-tidy==4.18.0 pyright==1.1.407 From 498efb614ae17782c619c33b9a791f58ab810b1d Mon Sep 17 00:00:00 2001 From: Guiliano99 Date: Sun, 2 Nov 2025 08:50:59 +0100 Subject: [PATCH 14/16] Add make dryrun test to pipeline. --- .github/workflows/check_quality.yml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/.github/workflows/check_quality.yml b/.github/workflows/check_quality.yml index c46f53ba..6819f560 100644 --- a/.github/workflows/check_quality.yml +++ b/.github/workflows/check_quality.yml @@ -36,6 +36,18 @@ jobs: - name: License check (reuse) run: docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" reuse lint + rf-run-able: + needs: prepare_env + runs-on: ubuntu-22.04 + env: + IMAGE: ${{ needs.prepare_env.outputs.image_lc }} + steps: + - uses: actions/checkout@v4 + - name: RobotFramework run-ability check + run: | + docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" \ + make dryrun + rf_style_check: needs: prepare_env runs-on: ubuntu-22.04 From 217fab1eaaef1b8fe53cd68bd3660a862dcbd3d1 Mon Sep 17 00:00:00 2001 From: Guiliano99 Date: Sun, 2 Nov 2025 08:54:59 +0100 Subject: [PATCH 15/16] Change liboqs-python to branch from Guiliano99. --- data/dockerfiles/Dockerfile.base | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/dockerfiles/Dockerfile.base b/data/dockerfiles/Dockerfile.base index d5cd07c0..88491aba 100644 --- a/data/dockerfiles/Dockerfile.base +++ b/data/dockerfiles/Dockerfile.base @@ -17,8 +17,8 @@ RUN pip3 install --upgrade pip && \ pip3 install -r /app/requirements.txt # Build and install liboqs-python -RUN git clone --depth=1 https://github.com/open-quantum-safe/liboqs-python && \ - pip3 install ./liboqs-python && \ +RUN git clone --depth=1 https://github.com/Guiliano99/liboqs-python-stateful-sig && \ + pip3 install ./liboqs-python-stateful-sig && \ python3 -c "import oqs" # Trigger the build of liboqs, by importing it # Remove unnecessary packages after we're done From fff6d1ab817903d468846bc92a96dfcdf67c9c04 Mon Sep 17 00:00:00 2001 From: Guiliano99 Date: Sun, 2 Nov 2025 09:38:20 +0100 Subject: [PATCH 16/16] Add check_quality.yml hob rf-run-able. - Verifies if the rf-test are run able or something went wrong. --- .github/workflows/check_quality.yml | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/.github/workflows/check_quality.yml b/.github/workflows/check_quality.yml index 6819f560..deffdaee 100644 --- a/.github/workflows/check_quality.yml +++ b/.github/workflows/check_quality.yml @@ -37,17 +37,42 @@ jobs: run: docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" reuse lint rf-run-able: + # Checks if the RobotFramework tests can be executed (dryrun). If not, uploads the artifacts for debugging. + # Sometimes it is import error or some sub dependency missing, this helps to identify such issues early. needs: prepare_env runs-on: ubuntu-22.04 env: IMAGE: ${{ needs.prepare_env.outputs.image_lc }} steps: - uses: actions/checkout@v4 + + # 1) Run dryrun but don't stop the job on failure - name: RobotFramework run-ability check + id: dryrun + continue-on-error: true run: | + set -euo pipefail docker run --rm -v "$PWD:/workspace" -w /workspace "$IMAGE" \ make dryrun + # 2) Upload ONLY if the dryrun step failed + - name: Upload RobotFramework artifacts (only if dryrun failed) + if: ${{ steps.dryrun.outcome == 'failure' }} + uses: actions/upload-artifact@v4 + with: + name: robot-dryrun-artifacts-${{ github.run_id }} + path: | + ./output.xml + ./log.html + ./report.html + if-no-files-found: warn + retention-days: 14 + + # 3) Fail the job if dryrun failed (after uploading) + - name: Mark job as failed if dryrun failed + if: ${{ steps.dryrun.outcome == 'failure' }} + run: exit 1 + rf_style_check: needs: prepare_env runs-on: ubuntu-22.04