Harden degraded-mode contract coverage #768
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: CI | |
| on: | |
| push: | |
| branches: [main, develop] | |
| pull_request: | |
| workflow_dispatch: | |
| jobs: | |
| build: | |
| name: build (${{ matrix.os }}) | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| os: | |
| - ubuntu-22.04 | |
| - ubuntu-24.04 | |
| runs-on: ${{ matrix.os }} | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y clang llvm libbpf-dev libsystemd-dev pkg-config cmake ninja-build python3-jsonschema libgtest-dev linux-tools-common linux-tools-$(uname -r) || sudo apt-get install -y clang llvm libbpf-dev libsystemd-dev pkg-config cmake ninja-build python3-jsonschema libgtest-dev linux-tools-common | |
| - name: Configure | |
| run: cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DSKIP_BPF_BUILD=ON | |
| - name: Build | |
| run: cmake --build build | |
| - name: Binary-hardening contract | |
| run: bash scripts/check_hardening.sh build/aegisbpf | |
| test: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y clang llvm libbpf-dev libsystemd-dev pkg-config cmake ninja-build python3-jsonschema libgtest-dev linux-tools-common linux-tools-$(uname -r) || sudo apt-get install -y clang llvm libbpf-dev libsystemd-dev pkg-config cmake ninja-build python3-jsonschema libgtest-dev linux-tools-common | |
| - name: Configure | |
| run: cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -DSKIP_BPF_BUILD=ON | |
| - name: Build | |
| run: cmake --build build | |
| - name: Run tests | |
| run: ctest --test-dir build --output-on-failure --timeout 120 | |
| sanitizers: | |
| name: sanitizers (${{ matrix.sanitizer }}) | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| sanitizer: | |
| - asan | |
| - ubsan | |
| - tsan | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y clang llvm libbpf-dev libsystemd-dev pkg-config cmake ninja-build linux-tools-common linux-tools-$(uname -r) || sudo apt-get install -y clang llvm libbpf-dev libsystemd-dev pkg-config cmake ninja-build linux-tools-common | |
| - name: Configure with ${{ matrix.sanitizer }} | |
| run: | | |
| cmake -S . -B build -G Ninja \ | |
| -DCMAKE_BUILD_TYPE=Debug \ | |
| -DBUILD_TESTING=ON \ | |
| -DBUILD_BENCHMARKS=OFF \ | |
| -DSKIP_BPF_BUILD=ON \ | |
| -DCMAKE_C_COMPILER=clang \ | |
| -DCMAKE_CXX_COMPILER=clang++ \ | |
| -DENABLE_ASAN=${{ matrix.sanitizer == 'asan' && 'ON' || 'OFF' }} \ | |
| -DENABLE_UBSAN=${{ matrix.sanitizer == 'ubsan' && 'ON' || 'OFF' }} \ | |
| -DENABLE_TSAN=${{ matrix.sanitizer == 'tsan' && 'ON' || 'OFF' }} | |
| - name: Build | |
| run: cmake --build build | |
| - name: Run tests with sanitizer | |
| run: | | |
| ctest --test-dir build --output-on-failure --timeout 300 | |
| env: | |
| ASAN_OPTIONS: abort_on_error=1:halt_on_error=1 | |
| UBSAN_OPTIONS: print_stacktrace=1:halt_on_error=1 | |
| TSAN_OPTIONS: abort_on_error=1:halt_on_error=1 | |
| coverage: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y clang llvm libbpf-dev libsystemd-dev pkg-config cmake ninja-build gcovr python3-jsonschema libgtest-dev linux-tools-common linux-tools-$(uname -r) || sudo apt-get install -y clang llvm libbpf-dev libsystemd-dev pkg-config cmake ninja-build gcovr python3-jsonschema libgtest-dev linux-tools-common | |
| - name: Configure with coverage | |
| run: cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -DENABLE_COVERAGE=ON -DSKIP_BPF_BUILD=ON | |
| - name: Build | |
| run: cmake --build build | |
| - name: Run tests | |
| run: ctest --test-dir build --output-on-failure --timeout 120 | |
| - name: Load coverage thresholds | |
| run: | | |
| python3 - <<'PY' | |
| import os | |
| import json | |
| cfg = json.load(open("config/coverage_thresholds.json", "r", encoding="utf-8")) | |
| with open(os.environ["GITHUB_ENV"], "a", encoding="utf-8") as env: | |
| env.write(f"COVERAGE_MIN_LINE={int(cfg['line_min'])}\n") | |
| env.write(f"COVERAGE_MIN_BRANCH={int(cfg['branch_min'])}\n") | |
| PY | |
| - name: Generate coverage report | |
| run: | | |
| gcovr --root . --object-directory build --exclude tests --exclude build/_deps \ | |
| --merge-mode-functions=merge-use-line-min \ | |
| --print-summary \ | |
| --fail-under-line ${COVERAGE_MIN_LINE} \ | |
| --fail-under-branch ${COVERAGE_MIN_BRANCH} \ | |
| --xml coverage.xml \ | |
| --html coverage.html \ | |
| --html-details | |
| - name: Upload coverage to Codecov | |
| uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 | |
| with: | |
| files: coverage.xml | |
| flags: unittests | |
| fail_ci_if_error: false | |
| - name: Upload coverage HTML | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: coverage-report | |
| path: coverage*.html | |
| smoke-test: | |
| runs-on: ubuntu-24.04 | |
| if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y clang llvm libbpf-dev libsystemd-dev pkg-config cmake ninja-build linux-tools-common linux-tools-$(uname -r) || sudo apt-get install -y clang llvm libbpf-dev libsystemd-dev pkg-config cmake ninja-build linux-tools-common | |
| - name: Check BPF LSM availability | |
| id: check_lsm | |
| run: | | |
| if grep -q bpf /sys/kernel/security/lsm 2>/dev/null; then | |
| echo "bpf_lsm=true" >> $GITHUB_OUTPUT | |
| else | |
| echo "bpf_lsm=false" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Configure | |
| run: cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DSKIP_BPF_BUILD=ON | |
| - name: Build | |
| run: cmake --build build | |
| - name: Detect built BPF object | |
| id: bpf_obj | |
| run: | | |
| if [[ -f build/aegis.bpf.o ]]; then | |
| echo "present=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "present=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Run health check | |
| if: steps.bpf_obj.outputs.present == 'true' | |
| run: sudo ./build/aegisbpf health | |
| - name: Skip health check when BPF object is not built | |
| if: steps.bpf_obj.outputs.present != 'true' | |
| run: echo "Skipping health check because SKIP_BPF_BUILD=ON (no build/aegis.bpf.o)." | |
| - name: Run smoke test (audit mode) | |
| if: steps.check_lsm.outputs.bpf_lsm == 'true' && steps.bpf_obj.outputs.present == 'true' | |
| timeout-minutes: 1 | |
| run: | | |
| sudo timeout 5 ./build/aegisbpf run --audit || true | |
| echo "Smoke test completed" | |
| build-arm64: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - uses: docker/setup-qemu-action@06116385d9baf250c9f4dcb4858b16962ea869c3 # v4.1.0 | |
| - name: Build (arm64 via QEMU) | |
| run: | | |
| docker run --rm --platform linux/arm64 \ | |
| -v "$PWD":/src \ | |
| -v /sys:/sys:ro \ | |
| -w /src \ | |
| ubuntu:24.04 \ | |
| bash -lc "apt-get update && apt-get install -y clang llvm libbpf-dev libsystemd-dev pkg-config cmake ninja-build && cmake -S . -B build-arm64 -G Ninja -DBUILD_TESTING=OFF -DSKIP_BPF_BUILD=ON && cmake --build build-arm64" | |
| lint: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y clang-format cppcheck | |
| - name: Check clang-format | |
| run: | | |
| find src tests -name '*.cpp' -o -name '*.hpp' | xargs clang-format --dry-run --Werror | |
| - name: Run cppcheck | |
| run: | | |
| cppcheck --std=c++20 --enable=all --error-exitcode=1 --inline-suppr \ | |
| --suppress=missingIncludeSystem \ | |
| --suppress=unmatchedSuppression \ | |
| --suppress=syntaxError:tests/test_commands.cpp \ | |
| --suppress=syntaxError:tests/test_kernel_features.cpp \ | |
| --suppress=syntaxError:tests/test_metrics.cpp \ | |
| --suppress=syntaxError:tests/test_tracing.cpp \ | |
| --suppress=syntaxError:tests/test_crypto_safe.cpp \ | |
| --suppress=syntaxError:tests/test_bpf_integrity.cpp \ | |
| --suppress=syntaxError:tests/test_bpf_signing.cpp \ | |
| --suppress=syntaxError:tests/test_exec_identity.cpp \ | |
| --suppress=syntaxError:tests/test_ocsf_formatter.cpp \ | |
| --suppress=syntaxError:tests/test_cef_formatter.cpp \ | |
| --suppress=syntaxError:tests/test_bpf_link_pin.cpp \ | |
| --suppress=syntaxError:tests/test_posture_gate.cpp \ | |
| --suppress=syntaxError:tests/bpf/test_bpf_prog_run.cpp \ | |
| --suppress=useStlAlgorithm \ | |
| --suppress=constParameterReference \ | |
| --suppress=constVariablePointer \ | |
| --suppress=knownConditionTrueFalse \ | |
| --suppress=unusedFunction \ | |
| --suppress=checkersReport \ | |
| --suppress=checkLevelNormal \ | |
| -I src \ | |
| src/ tests/ | |
| policy-tags: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Validate MITRE ATT&CK tag headers | |
| run: ./scripts/validate_mitre_tags.sh | |
| required-checks-contract: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y python3-yaml | |
| - name: Validate required check definitions | |
| run: | | |
| python3 scripts/validate_required_checks.py \ | |
| --required config/required_checks.txt \ | |
| --required config/required_checks_release.txt | |
| python3 scripts/validate_ci_workflow_policy.py | |
| label-contract: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y python3-yaml | |
| - name: Validate label contract | |
| run: python3 scripts/validate_label_contract.py | |
| capability-contract: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Validate capability posture contract | |
| run: python3 scripts/validate_capability_posture_contract.py | |
| enforcement-proof-contract: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Validate enforcement proof contract | |
| run: python3 scripts/validate_enforcement_proof_contract.py | |
| - name: Machine-checked enforcement proofs (Z3) + model-fidelity guard | |
| run: proofs/run.sh | |
| - name: Validate kernel-compat manifest is in sync with the source of truth | |
| run: python3 scripts/gen_kernel_compat_manifest.py --check | |
| - name: Validate bpfcompat manifest is in sync with the BPF source | |
| run: python3 scripts/gen_bpfcompat_manifest.py --check | |
| helm-posture-contract: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Validate Helm posture contract | |
| run: python3 tests/check_helm_posture_contract.py | |
| ops-observability-contract: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Validate ops observability contract | |
| run: | | |
| python3 scripts/validate_grafana_dashboard.py config/grafana/aegisbpf-ops-minimal.json | |
| python3 tests/check_ops_observability_contract.py | |
| k8s-rollout-contract: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Validate Kubernetes rollout contract | |
| run: python3 tests/check_k8s_rollout_contract.py | |
| guarantees-contract: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Validate enforcement guarantees contract | |
| run: python3 tests/check_guarantees_contract.py | |
| clang-tidy: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y clang-tidy clang llvm libbpf-dev libsystemd-dev pkg-config cmake ninja-build libgtest-dev libbenchmark-dev | |
| - name: Configure | |
| run: cmake -S . -B build-clang-tidy -G Ninja -DCMAKE_BUILD_TYPE=Debug -DBUILD_TESTING=ON -DSKIP_BPF_BUILD=ON | |
| - name: Run clang-tidy on changed files | |
| env: | |
| BASE_REF: ${{ github.base_ref }} | |
| DIFF_RANGE: ${{ github.event_name == 'push' && format('{0}...{1}', github.event.before, github.sha) || '' }} | |
| BUILD_DIR: build-clang-tidy | |
| run: scripts/run_clang_tidy_changed.sh | |
| smoke-fuzz: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y clang llvm libbpf-dev pkg-config cmake ninja-build | |
| - name: Configure with fuzzing | |
| env: | |
| CC: clang | |
| CXX: clang++ | |
| run: cmake -S . -B build-fuzz -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_FUZZING=ON -DBUILD_TESTING=OFF -DSKIP_BPF_BUILD=ON | |
| - name: Build fuzz targets | |
| run: cmake --build build-fuzz --target fuzz_policy fuzz_bundle fuzz_network fuzz_path fuzz_event | |
| - name: Smoke fuzz (60s per target, seeded corpus) | |
| run: | | |
| # Use a writable copy of the seed corpus so libFuzzer can add | |
| # discovered inputs during the run without modifying the tree. | |
| for target in fuzz_policy fuzz_bundle fuzz_network fuzz_path fuzz_event; do | |
| echo "Fuzzing ${target}..." | |
| runtime_corpus="$(mktemp -d)/${target}" | |
| mkdir -p "${runtime_corpus}" | |
| if [ -d "tests/fuzz/corpus/${target}" ]; then | |
| cp -a "tests/fuzz/corpus/${target}/." "${runtime_corpus}/" | |
| fi | |
| # fuzz_event prints JSON to stdout for every mutation; silence it | |
| # so CI logs stay readable. libFuzzer stats go to stderr. | |
| if [ "${target}" = "fuzz_event" ]; then | |
| ./build-fuzz/${target} "${runtime_corpus}" -max_total_time=60 -print_final_stats=1 >/dev/null | |
| else | |
| ./build-fuzz/${target} "${runtime_corpus}" -max_total_time=60 -print_final_stats=1 | |
| fi | |
| done | |
| - name: Upload fuzz crash artifacts | |
| if: failure() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: fuzz-crashes | |
| path: | | |
| crash-* | |
| build-fuzz/crash-* | |
| parser-fuzz: | |
| runs-on: ubuntu-24.04 | |
| if: github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Install dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y clang llvm libbpf-dev pkg-config cmake ninja-build | |
| - name: Configure with fuzzing | |
| env: | |
| CC: clang | |
| CXX: clang++ | |
| run: cmake -S . -B build-fuzz -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DENABLE_FUZZING=ON -DBUILD_TESTING=OFF -DSKIP_BPF_BUILD=ON | |
| - name: Build parser fuzz targets | |
| run: cmake --build build-fuzz --target fuzz_policy fuzz_bundle fuzz_network fuzz_path fuzz_event | |
| - name: Run parser fuzz gate on changed files | |
| env: | |
| BASE_REF: ${{ github.base_ref }} | |
| DIFF_RANGE: ${{ github.event_name == 'push' && format('{0}...{1}', github.event.before, github.sha) || '' }} | |
| BUILD_DIR: build-fuzz | |
| FUZZ_SECONDS: "120" | |
| run: scripts/run_parser_fuzz_changed.sh | |
| sbom: | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 | |
| - name: Generate SBOM | |
| uses: anchore/sbom-action@d94f46e13c6c62f59525ac9a1e147a99dc0b9bf5 # v0.17.0 | |
| with: | |
| format: spdx-json | |
| output-file: sbom.spdx.json | |
| - name: Upload SBOM | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: sbom | |
| path: sbom.spdx.json |