From 700c9eb49dfdc30583312d1a6803c1b799bf79ea Mon Sep 17 00:00:00 2001 From: Raul Metsma Date: Tue, 18 Aug 2026 11:20:38 +0300 Subject: [PATCH] Harden building and CI IB-9053 Signed-off-by: Raul Metsma --- .github/dependabot.yml | 6 +++ .github/workflows/build.yml | 68 +++++++++++++++++++------------- client/download_tsl.py | 13 +++++- common | 2 +- prepare_osx_build_environment.sh | 47 +++++++++++++--------- 5 files changed, 89 insertions(+), 47 deletions(-) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..ca79ca5b4 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: github-actions + directory: / + schedule: + interval: weekly diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d690d1c84..2f1e9c142 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,6 +2,9 @@ name: CI on: [push, pull_request] permissions: contents: read +concurrency: + group: ${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true env: BUILD_NUMBER: ${{ github.run_number }} CMAKE_BUILD_PARALLEL_LEVEL: 4 @@ -10,17 +13,19 @@ jobs: macos: name: Build on macOS runs-on: macos-latest + timeout-minutes: 120 env: MACOSX_DEPLOYMENT_TARGET: 14.0 LIBS_PATH: ${{ github.workspace }}/cache steps: - &Checkout name: Checkout - uses: actions/checkout@v6 + uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6.1.0 with: submodules: recursive + persist-credentials: false - name: Download artifact - uses: dawidd6/action-download-artifact@v20 + uses: dawidd6/action-download-artifact@8305c0f1062bb0d184d09ef4493ecb9288447732 # v20 with: workflow: build.yml branch: master @@ -30,12 +35,13 @@ jobs: - name: Install dependencies run: | brew install flatbuffers - curl -O -L -s https://installer.id.ee/media/github/opensc_0.26.1.pkg + curl -O -sS --fail-with-body -L --retry 3 --proto '=https' --proto-redir '=https' https://installer.id.ee/media/github/opensc_0.26.1.pkg + echo "db30c6dee3d362d3003f26a2f0478161f222e3074364de58d62e34ce247d31b1 opensc_0.26.1.pkg" | shasum -a 256 -c - sudo installer -verboseR -pkg libdigidocpp-pkg/build/macos/libdigidocpp*.pkg -target / sudo installer -verboseR -pkg opensc_*.pkg -target / rm -rf libdigidocpp-pkg - name: Cache libraries - uses: actions/cache@v5 + uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0 with: path: ${{ env.LIBS_PATH }} key: vcpkg-macOS-${{ hashFiles('prepare_osx_build_environment.sh') }} @@ -44,7 +50,7 @@ jobs: mkdir -p ${LIBS_PATH}/Qt-6.10.3-OpenSSL ./prepare_osx_build_environment.sh -p ${LIBS_PATH} - name: Install Qt - uses: jurplel/install-qt-action@v4 + uses: jurplel/install-qt-action@48d3ad6db93f3627c8ee7a0454bc6f3744f7e730 # v4.3.1 with: version: 6.10.3 arch: clang_64 @@ -60,13 +66,14 @@ jobs: cmake --build build --target macdeployqt cmake --build build --target zip - name: Archive artifacts - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: macOS path: build/qdigidoc4*.zip ubuntu: name: Build on Ubuntu ${{ matrix.container }} ${{ matrix.arch }} runs-on: ubuntu-24.04${{ matrix.arch == 'arm64' && '-arm' || '' }} + timeout-minutes: 120 container: ubuntu:${{ matrix.container }} strategy: matrix: @@ -78,7 +85,7 @@ jobs: DEBEMAIL: github-actions@github.com steps: - name: Download artifact - uses: dawidd6/action-download-artifact@v20 + uses: dawidd6/action-download-artifact@8305c0f1062bb0d184d09ef4493ecb9288447732 # v20 with: workflow: build.yml branch: master @@ -113,20 +120,21 @@ jobs: - name: Lintian run: lintian *.deb; - name: Archive artifacts - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: ubuntu_${{ matrix.container }}_${{ matrix.arch }} path: qdigidoc4*.* fedora: name: Build on Fedora ${{ matrix.container }} runs-on: ubuntu-latest + timeout-minutes: 120 container: fedora:${{ matrix.container }} strategy: matrix: container: [43, 44] steps: - name: Download artifact - uses: dawidd6/action-download-artifact@v20 + uses: dawidd6/action-download-artifact@8305c0f1062bb0d184d09ef4493ecb9288447732 # v20 with: workflow: build.yml branch: master @@ -141,13 +149,14 @@ jobs: cmake -DCMAKE_INSTALL_PREFIX=/usr -B build -S . cmake --build build --target all package - name: Archive artifacts - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: fedora_${{ matrix.container }} path: build/qdigidoc4*.rpm windows: name: Build on Windows runs-on: windows-2022 + timeout-minutes: 120 strategy: matrix: vcver: [143] @@ -157,7 +166,7 @@ jobs: steps: - *Checkout - name: Download artifact - uses: dawidd6/action-download-artifact@v20 + uses: dawidd6/action-download-artifact@8305c0f1062bb0d184d09ef4493ecb9288447732 # v20 with: workflow: build.yml branch: master @@ -170,17 +179,17 @@ jobs: $r = Start-Process msiexec -ArgumentList '/a', 'libdigidocpp.msi', '/qn', "TARGETDIR=$env:GITHUB_WORKSPACE\libs", '/l*v', 'install.log' -Wait -PassThru if ($r.ExitCode -ne 0) { Get-Content install.log; exit $r.ExitCode } - name: Cache vcpkg - uses: actions/cache@v5 + uses: actions/cache@caa296126883cff596d87d8935842f9db880ef25 # v5.1.0 with: path: ${{ github.workspace }}/vcpkg_cache key: vcpkg-${{ matrix.vcver }}-${{ matrix.platform }}-${{ hashFiles('client/libcdoc/vcpkg.json') }} - name: Install Qt - uses: jurplel/install-qt-action@v4 + uses: jurplel/install-qt-action@48d3ad6db93f3627c8ee7a0454bc6f3744f7e730 # v4.3.1 with: version: 6.11.1 arch: ${{ matrix.platform == 'arm64' && 'win64_msvc2022_arm64_cross_compiled' || 'win64_msvc2022_64' }} cache: true - aqtsource: git+https://github.com/miurahr/aqtinstall.git + aqtsource: git+https://github.com/miurahr/aqtinstall.git@16db45a70b5905ad596941b223469bc86a56901e - name: Install WiX run: | dotnet tool install -g wix --version 6.0.2 @@ -201,7 +210,7 @@ jobs: cmake --build build --target msishellext cmake --build build --target appx - name: Archive artifacts - uses: actions/upload-artifact@v7 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: msi_${{ matrix.vcver }}_${{ matrix.platform }} path: | @@ -211,13 +220,11 @@ jobs: name: Run Coverity tests if: github.repository == 'open-eid/DigiDoc4-Client' && contains(github.ref, 'coverity_scan') runs-on: ubuntu-24.04 - env: - TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} - PROJECTNAME: open-eid/DigiDoc4-Client + timeout-minutes: 120 steps: - *Checkout - name: Download artifact - uses: dawidd6/action-download-artifact@v20 + uses: dawidd6/action-download-artifact@8305c0f1062bb0d184d09ef4493ecb9288447732 # v20 with: workflow: build.yml branch: master @@ -227,8 +234,11 @@ jobs: - name: Install dependencies run: sudo apt update -qq && sudo apt install --no-install-recommends -y ${UBUNTU_DEPS} - name: Download Coverity Build Tool + env: + TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} + PROJECTNAME: open-eid/DigiDoc4-Client run: | - curl -sSfL \ + curl -sS --fail-with-body -L --retry 3 --proto '=https' --proto-redir '=https' \ --data-urlencode "token=${TOKEN}" \ --data-urlencode "project=${PROJECTNAME}" \ -o cov-analysis-linux64.tar.gz \ @@ -242,8 +252,11 @@ jobs: cov-build --dir cov-int make tar czvf upload.tgz cov-int - name: Submit the result to Coverity Scan + env: + TOKEN: ${{ secrets.COVERITY_SCAN_TOKEN }} + PROJECTNAME: open-eid/DigiDoc4-Client run: | - curl -sSfL \ + curl -sS --fail-with-body -L --retry 3 --proto '=https' --proto-redir '=https' \ -F project=$PROJECTNAME \ -F token=$TOKEN \ -F email=eid-teenusehaldus@ria.ee \ @@ -255,12 +268,13 @@ jobs: name: Run CodeQL tests if: github.repository == 'open-eid/DigiDoc4-Client' runs-on: ubuntu-24.04 + timeout-minutes: 120 permissions: security-events: write steps: - *Checkout - name: Download artifact - uses: dawidd6/action-download-artifact@v20 + uses: dawidd6/action-download-artifact@8305c0f1062bb0d184d09ef4493ecb9288447732 # v20 with: workflow: build.yml branch: master @@ -270,19 +284,19 @@ jobs: - name: Install dependencies run: sudo apt update -qq && sudo apt install --no-install-recommends -y ${UBUNTU_DEPS} - name: Initialize CodeQL - uses: github/codeql-action/init@v4 + uses: github/codeql-action/init@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7 with: languages: cpp queries: +security-and-quality - name: Autobuild - uses: github/codeql-action/autobuild@v4 + uses: github/codeql-action/autobuild@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v4 + uses: github/codeql-action/analyze@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7 with: upload: False output: sarif-results - name: Filter results - uses: advanced-security/filter-sarif@develop + uses: advanced-security/filter-sarif@2da736ff05ef065cb2894ac6892e47b5eac2c3c0 # v1.1 with: patterns: | -**/*autogen*/** @@ -292,6 +306,6 @@ jobs: input: sarif-results/cpp.sarif output: sarif-results/cpp.sarif - name: Upload results - uses: github/codeql-action/upload-sarif@v4 + uses: github/codeql-action/upload-sarif@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7 with: sarif_file: sarif-results/cpp.sarif diff --git a/client/download_tsl.py b/client/download_tsl.py index 0967fcb3e..4c017685e 100644 --- a/client/download_tsl.py +++ b/client/download_tsl.py @@ -7,6 +7,13 @@ import urllib.parse import time +def is_well_formed_xml(path): + try: + ET.parse(path) + return True + except ET.ParseError: + return False + def download_tsl_file(url, output_path, filename): output_file = os.path.join(output_path, filename) print(f"Downloading TSL list from: {url}") @@ -15,10 +22,14 @@ def download_tsl_file(url, output_path, filename): try: with urllib.request.urlopen(url, timeout=60) as response, open(output_file, 'wb') as f: shutil.copyfileobj(response, f) + if not is_well_formed_xml(output_file): + raise ValueError(f"downloaded file is not well-formed XML: {output_file}") print(f"Saved to: {output_file}") return output_file - except (urllib.error.HTTPError, urllib.error.URLError) as e: + except (urllib.error.HTTPError, urllib.error.URLError, ValueError) as e: print(f"Attempt {attempt + 1}/{retries} failed: {e}") + if os.path.exists(output_file): + os.remove(output_file) if attempt + 1 < retries: sleep_time = 10 * (attempt + 1) print(f"Retrying in {sleep_time} seconds...") diff --git a/common b/common index 78d45ae98..a2381bba4 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 78d45ae983ed2c0d9bc4de5d31f78cd46d13a48c +Subproject commit a2381bba4ee80ccee79cef1ed98666e87cb2c23c diff --git a/prepare_osx_build_environment.sh b/prepare_osx_build_environment.sh index 26c014e3e..382e79db1 100755 --- a/prepare_osx_build_environment.sh +++ b/prepare_osx_build_environment.sh @@ -1,17 +1,33 @@ #!/bin/bash -# Requires xcode and cmake, also OpenSSL has to be installed via homebrew. +# Requires xcode and cmake. set -e ######### Versions of libraries/frameworks to be compiled QT_VER="6.10.3" OPENSSL_VER="3.5.7" -OPENLDAP_VER="2.6.13" +OPENLDAP_VER="2.6.14" REBUILD=false BUILD_PATH=~/cmake_builds : ${MACOSX_DEPLOYMENT_TARGET:="14.0"} export MACOSX_DEPLOYMENT_TARGET +######### Checksums for the versions above; update alongside any version bump +OPENSSL_SHA256="a8c0d28a529ca480f9f36cf5792e2cd21984552a3c8e4aa11a24aa31aeac98e8" +QTBASE_SHA256="383dc907816338f0cba72088a524c07458dfc69ce684ca9132fcc4fe91c24b0b" +QTSVG_SHA256="b3223fe005f6a4c7f21f34e4ee6ce0094737cff9503ba15bbb171ac18794f76d" +QTTOOLS_SHA256="8f00b9e3d1f80973d81cff67684972b89993183ef19924404d5b8ff0f89675b6" +OPENLDAP_SHA256="806dcd21d366428187fba3278da773d5930f774852c9e92517f950d585f19107" + +verify_sha256() { + local file="$1" expected="$2" actual + actual=$(shasum -a 256 "${file}" | cut -d' ' -f1) + if [[ "${actual}" != "${expected}" ]]; then + echo -e "${RED}Checksum mismatch for ${file}: expected ${expected}, got ${actual}${RESET}" + exit 1 + fi +} + while [[ $# -gt 0 ]] do key="$1" @@ -25,31 +41,19 @@ do : ${OPENSSL_PATH:="${BUILD_PATH}/OpenSSL"} shift ;; - -q|--qt) - QT_VER="$2" - shift - ;; - -l|--openldap) - OPENLDAP_VER="$2" - shift - ;; -r|--rebuild) REBUILD=true ;; -h|--help) echo "Build Qt for Digidoc4 client" echo "" - echo "Usage: $0 [-r|--rebuild] [-p build-path] [-h|--help] [-q|--qt qt-version] [-l|--openldap openldap-version]" + echo "Usage: $0 [-r|--rebuild] [-p|--path build-path] [-o|--openssl openssl-path] [-h|--help]" echo "" echo "Options:" echo " -o or --openssl openssl-path:" echo " OpenSSL path; default ${OPENSSL_VER} will be built ${OPENSSL_PATH}" echo " -p or --path build-path" echo " folder where the dependencies should be built; default ${BUILD_PATH}" - echo " -q or --qt qt-version:" - echo " Specific version of Qt to build; default ${QT_VER} " - echo " -l or --openldap openldap-version:" - echo " Specific version of OpenLDAP to build; default ${OPENLDAP_VER} " echo " -r or --rebuild:" echo " Rebuild even if dependency is already built" echo " " @@ -74,8 +78,9 @@ pushd ${BUILD_PATH} if [[ ! -d ${OPENSSL_PATH} ]] ; then echo -e "\n${ORANGE}##### Building OpenSSL ${OPENSSL_VER} ${OPENSSL_PATH} #####${RESET}\n" if [ ! -f openssl-${OPENSSL_VER}.tar.gz ]; then - curl -O -L https://www.openssl.org/source/openssl-${OPENSSL_VER}.tar.gz + curl -O -L --proto '=https' --proto-redir '=https' https://www.openssl.org/source/openssl-${OPENSSL_VER}.tar.gz fi + verify_sha256 openssl-${OPENSSL_VER}.tar.gz ${OPENSSL_SHA256} rm -rf openssl-${OPENSSL_VER} tar xf openssl-${OPENSSL_VER}.tar.gz pushd openssl-${OPENSSL_VER} @@ -103,8 +108,13 @@ if [[ "$REBUILD" = true || ! -d ${QT_PATH} ]] ; then echo -e "\n${ORANGE}##### Building Qt ${QT_VER} ${QT_PATH} #####${RESET}\n" for PACKAGE in qtbase-everywhere-src-${QT_VER} qtsvg-everywhere-src-${QT_VER} qttools-everywhere-src-${QT_VER}; do if [ ! -f ${PACKAGE}.tar.xz ]; then - curl -O -L https://download.qt.io/official_releases/qt/${QT_MINOR}/${QT_VER}/submodules/${PACKAGE}.tar.xz + curl -O -L --proto '=https' --proto-redir '=https' https://download.qt.io/official_releases/qt/${QT_MINOR}/${QT_VER}/submodules/${PACKAGE}.tar.xz fi + case "${PACKAGE}" in + qtbase-*) verify_sha256 ${PACKAGE}.tar.xz ${QTBASE_SHA256} ;; + qtsvg-*) verify_sha256 ${PACKAGE}.tar.xz ${QTSVG_SHA256} ;; + qttools-*) verify_sha256 ${PACKAGE}.tar.xz ${QTTOOLS_SHA256} ;; + esac rm -rf ${PACKAGE} tar xf ${PACKAGE}.tar.xz pushd ${PACKAGE} @@ -127,8 +137,9 @@ fi if [[ "$REBUILD" = true || ! -d ${OPENLDAP_PATH} ]] ; then echo -e "\n${ORANGE}##### Building OpenLDAP ${OPENLDAP_VER} ${OPENLDAP_PATH} #####${RESET}\n" if [ ! -f openldap-${OPENLDAP_VER}.tgz ]; then - curl -O -L https://mirror.eu.oneandone.net/software/openldap/openldap-release/openldap-${OPENLDAP_VER}.tgz + curl -O -L --proto '=https' --proto-redir '=https' https://www.openldap.org/software/download/OpenLDAP/openldap-release/openldap-${OPENLDAP_VER}.tgz fi + verify_sha256 openldap-${OPENLDAP_VER}.tgz ${OPENLDAP_SHA256} tar xf openldap-${OPENLDAP_VER}.tgz pushd openldap-${OPENLDAP_VER} sed -ie 's! doc!!' Makefile.in