]> git.kaiwu.me - haproxy.git/commitdiff
CI: github: add AWS-LC FIPS testing workflow
authorWilliam Lallemand <wlallemand@irq6.net>
Fri, 23 Oct 2026 11:51:51 +0000 (11:51 +0000)
committerWilliam Lallemand <wlallemand@haproxy.com>
Mon, 2 Nov 2026 08:44:51 +0000 (08:44 +0000)
The FIPS branches of AWS-LC were covered by the VTest matrix, but only
built in non-FIPS mode: nothing exercised the FIPS-specific code paths in
HAProxy, in particular the compliance checks in src/fips.c which reject
non-approved ciphers, curves, signature algorithms and TLS versions at
configuration time.  A regression there is invisible until someone builds
HAProxy against an AWS-LC FIPS library.

Add a nightly workflow that builds AWS-LC with FIPS=1 and runs the VTest
and unit test suites against it, in the same way the other SSL library
workflows do.  It tests three sources, resolved through
determine_aws_lc():

  - AWS-LC 3.x, the fips-2024-09-27 branch;
  - AWS-LC 4.x, the fips-2025-09-12-lts branch;
  - the latest AWS-LC release tag, whose FIPS module is the one currently
    submitted for validation, so that the newest code is covered too
    instead of only the two maintenance branches.

Branch specs resolve to the head commit of the branch, which is passed as
AWS_LC_VERSION and downloaded as an immutable archive by build-ssl.sh, so
a run is reproducible and the build cache is only renewed when the branch
advances.  The resolved release and commit are both part of the cache
key, matching the version-specific identity used by the VTest job so the
two workflows never share a half-populated cache entry.

The workflow only runs on the upstream repository, or on manual dispatch
from a fork, like the other SSL library workflows.

Note that the AWS-LC latest release is not expected to be identical to
either FIPS branch; it is built in FIPS mode for its own FIPS module
version, which is what the extra job is meant to detect early.

.github/workflows/aws-lc-fips.yml [new file with mode: 0644]

diff --git a/.github/workflows/aws-lc-fips.yml b/.github/workflows/aws-lc-fips.yml
new file mode 100644 (file)
index 0000000..8b31b04
--- /dev/null
@@ -0,0 +1,122 @@
+name: AWS-LC (FIPS)
+
+on:
+  schedule:
+    - cron: "0 0 * * *"
+  workflow_dispatch:
+
+permissions:
+  contents: read
+
+jobs:
+  Test:
+    name: ${{ matrix.name }}
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        include:
+          # Same AWS-LC sources as in the VTest job, built in FIPS mode
+          - name: AWS-LC 3.x (FIPS)
+            ssl: AWS_LC_VERSION=branch-fips-2024-09-27
+            # Shared by runs-on and the cache key for all three jobs.
+            os: &runner ubuntu-latest
+          - name: AWS-LC 4.x (FIPS)
+            ssl: AWS_LC_VERSION=branch-fips-2025-09-12-lts
+            os: *runner
+          - name: AWS-LC latest (FIPS)
+            ssl: AWS_LC_VERSION=latest
+            os: *runner
+      fail-fast: false
+    if: ${{ github.repository_owner == 'haproxy' || github.event_name == 'workflow_dispatch' }}
+    steps:
+      - uses: actions/checkout@v6
+      - name: Determine AWS-LC sources for ${{ matrix.name }}
+        id: get_aws_lc_release
+        env:
+          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+        run: |
+          result=$(cd .github && python3 - <<'PY'
+          from matrix import determine_aws_lc_branch, determine_latest_aws_lc
+
+          ssl = '${{ matrix.ssl }}'
+          if ssl.startswith('AWS_LC_VERSION=branch-'):
+              ssl, name = determine_aws_lc_branch(ssl)
+          else:
+              ssl = determine_latest_aws_lc(ssl)
+              name = ssl
+          print(name)
+          print(ssl)
+          PY
+          )
+          echo "$result"
+          echo "name=$(echo "$result" | head -n 1 | cut -d= -f2)" >> $GITHUB_OUTPUT
+          echo "result=$(echo "$result" | tail -n 1)" >> $GITHUB_OUTPUT
+      - name: Cache AWS-LC
+        id: cache_aws_lc
+        uses: actions/cache@v5
+        with:
+          path: '~/opt/'
+          key: ssl-${{ steps.get_aws_lc_release.outputs.name }}-fips-${{ matrix.os }}-gcc
+      - name: Install apt dependencies
+        run: |
+          sudo apt-get update -o Acquire::Languages=none -o Acquire::Translation=none
+          sudo apt-get --no-install-recommends -y install socat gdb jose
+      - name: Install AWS-LC
+        if: ${{ steps.cache_aws_lc.outputs.cache-hit != 'true' }}
+        run: env FIPS=1 ${{ steps.get_aws_lc_release.outputs.result }} scripts/build-ssl.sh
+      - name: Compile HAProxy
+        run: |
+          make -j$(nproc) ERR=1 CC=gcc TARGET=linux-glibc \
+            USE_OPENSSL_AWSLC=1 USE_QUIC=1 USE_ECH=1 \
+            SSL_LIB=${HOME}/opt/lib SSL_INC=${HOME}/opt/include \
+            DEBUG="-DDEBUG_POOL_INTEGRITY -DDEBUG_UNIT" \
+            ADDLIB="-Wl,-rpath,/usr/local/lib/ -Wl,-rpath,$HOME/opt/lib/"
+          sudo make install
+      - name: Show HAProxy version
+        id: show-version
+        run: |
+          ldd $(which haproxy)
+          haproxy -vv
+          echo "version=$(haproxy -vq)" >> $GITHUB_OUTPUT
+      - uses: ./.github/actions/setup-vtest
+      - name: Run VTest for HAProxy
+        id: vtest
+        run: |
+          make reg-tests VTEST_PROGRAM="$GITHUB_WORKSPACE/vtest/vtest" REGTESTS_TYPES=default,bug,devel
+      - name: Run Unit tests
+        id: unittests
+        run: |
+          make unit-tests
+      - name: Show VTest results
+        if: ${{ failure() && steps.vtest.outcome == 'failure' }}
+        run: |
+          for folder in ${TMPDIR:-/tmp}/haregtests-*/vtc.*; do
+            printf "::group::"
+            cat $folder/INFO
+            cat $folder/LOG
+            echo "::endgroup::"
+          done
+          exit 1
+      - name: Show coredumps
+        if: ${{ failure() && steps.vtest.outcome == 'failure' }}
+        run: |
+          failed=false
+          shopt -s nullglob
+          for file in /tmp/core/core.*; do
+            failed=true
+            printf "::group::"
+            gdb -ex 'thread apply all bt full' ./haproxy $file
+            echo "::endgroup::"
+          done
+          if [ "$failed" = true ]; then
+            exit 1;
+          fi
+      - name: Show Unit-Tests results
+        if: ${{ failure() && steps.unittests.outcome == 'failure' }}
+        run: |
+          for result in ${TMPDIR:-/tmp}/ha-unittests-*/results/res.*; do
+            printf "::group::"
+            cat $result
+            echo "::endgroup::"
+          done
+          exit 1