Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

e2e: check measurements reproducibility test for images #3654

Open
wants to merge 32 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
d00ad8c
started implementation
miampf Jan 21, 2025
3303b07
only build measured boot cmd
miampf Jan 23, 2025
1feaccd
fix workflow
miampf Jan 23, 2025
2068506
compute measurements for single image
miampf Jan 23, 2025
66155cb
install systemdUkify tools
miampf Jan 23, 2025
253a9ae
use `sudo -E` and add a check if `systemd-dissect` is in PATH
miampf Jan 23, 2025
20c78af
Carry over `PATH` explicitly using `env`
miampf Jan 28, 2025
c209d44
fix typo
miampf Jan 28, 2025
5377d81
Download v2.20.0 release measurements and check
miampf Jan 28, 2025
f440427
Compare all measurements against respective targets
miampf Jan 28, 2025
827f290
Add info echo
miampf Jan 30, 2025
dbb758e
pipefail + extglob
miampf Jan 30, 2025
04ea3c7
Explicitly install jq over nix
miampf Jan 30, 2025
3549a15
Actually only compare measurements
miampf Jan 30, 2025
bda1678
Delete `warnOnly` fields + debug logs
miampf Jan 30, 2025
48b1e82
improve jq filter
miampf Feb 5, 2025
a0b9963
delete expected zeroes from own measurements as well
miampf Feb 5, 2025
f3cf8be
Add some comments that explain the `jq` filters
miampf Feb 5, 2025
a154182
reference selection
miampf Feb 5, 2025
4482c38
Rename env var to RELEASETAG
miampf Feb 5, 2025
785e549
use correct ternary syntax
miampf Feb 5, 2025
8d73e31
Make workflow workflow_call
miampf Feb 18, 2025
8bc12b0
Call workflow in release
miampf Feb 18, 2025
df04e7b
split jq command into multiple lines
miampf Feb 18, 2025
4c94dfb
fix shellcheck issues
miampf Feb 18, 2025
b384971
split workflow into multiple steps
miampf Feb 20, 2025
730a532
`set -euo pipefail` & use github outputs
miampf Feb 20, 2025
bc58333
Set extglob at correct step
miampf Feb 20, 2025
72a3c90
Only select required field
miampf Feb 20, 2025
1a3ccb0
Collect all errors before exiting
miampf Feb 20, 2025
5c55142
Please shellcheck
miampf Feb 20, 2025
d480781
Remove test error
miampf Feb 20, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions .github/workflows/check-measurements-reproducibility.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
name: Check measurements reproducibility
on:
workflow_dispatch:
inputs:
releasetag:
type: string
description: The release to checkout and download.
required: true
workflow_call:
inputs:
releasetag:
type: string
description: The release to checkout and download.
required: true
Comment on lines +3 to +14
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We only create a release tag when publishing the release, so this won't work when calling this workflow during the release pipeline.
Instead, we should accept a version and ref as input.

Where version is the version of the measurements to download from the CDN,
and ref the git ref to check out and build the images from.
For the release workflow this should be the working branch, for workflow_dispatch this can be the same as version, i.e. the tag of the release


jobs:
check-reproducibility:
runs-on: ubuntu-22.04
steps:
- name: Checkout
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ github.event.inputs.releasetag }}
- name: Set up bazel
uses: ./.github/actions/setup_bazel_nix
with:
useCache: "false"
nixTools: |
systemdUkify
jq
jd-diff-patch
moreutils
- name: Build images
id: build-images
run: |
set -euo pipefail

# Build required binaries
bazel build //image/system:stable
bazel build //image/measured-boot/cmd
echo "buildPath=$PWD/bazel-bin/image" | tee -a "$GITHUB_OUTPUT"
cd "$(mktemp -d)"

- name: Download measurements
run: |
curl -O https://cdn.confidential.cloud/constellation/v2/ref/-/stream/stable/${{ github.event.inputs.releasetag }}/image/measurements.json

- name: Cleanup release measurements and generate our own
run: |
set -euo pipefail
shopt -s extglob

for directory in ${{ steps.build-images.outputs.buildPath }}/system/!(mkosi_wrapper.sh); do
dirname="$(basename "$directory")"
csp="$(echo "$dirname" | cut -d_ -f1)"
attestationVariant="$(echo "$dirname" | cut -d_ -f2)"

echo "Comparing measurements of CSP $csp with attestation variant $attestationVariant"
# This jq filter selects the measurements for the correct CSP and attestation variant
# and then removes all `warnOnly: true` measurements.
jq --arg attestation_variant "$attestationVariant" --arg csp "$csp" \
'
.list.[]
| select(
.attestationVariant == $attestation_variant
)
| select((.csp | ascii_downcase) == $csp)
| .measurements
| walk(
if (
type=="object" and .warnOnly
)
then del(.) else . end
)
| del(..|nulls)
| del(.[] .warnOnly)
' \
measurements.json > "$attestationVariant"_their-measurements.json

sudo env "PATH=$PATH" "${{ steps.build-images.outputs.buildPath }}/measured-boot/cmd/cmd_/cmd" "$directory/constellation" ./"$attestationVariant"_own-measurements.json
jq '.measurements' ./"$attestationVariant"_own-measurements.json | sponge ./"$attestationVariant"_own-measurements.json
done

- name: Compare measurements
run: |
# no -e since we need to collect errors later
set -uo pipefail
shopt -s extglob

declare -A errors

for directory in ${{ steps.build-images.outputs.buildPath }}/system/!(mkosi_wrapper.sh); do
dirname="$(basename "$directory")"
attestationVariant="$(echo "$dirname" | cut -d_ -f2)"

echo "Their measurements for $attestationVariant:"
ts " " < "$attestationVariant"_their-measurements.json
echo "Own measurements for $attestationVariant:"
ts " " < "$attestationVariant"_own-measurements.json

# TODO: cache errors and return them later.
if ! jd ./"$attestationVariant"_their-measurements.json ./"$attestationVariant"_own-measurements.json; then
errors["$attestationVariant"]="$(!!)"
fi
done

for attestationVariant in "${!errors[@]}"; do
echo "Failed to reproduce measurements for $attestationVariant:"
echo "${errors["$attestationVariant"]}" | ts " "
done

if [[ "${#errors[@]}" -ne 0 ]]; then
exit 1
fi
7 changes: 7 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,13 @@ jobs:
stream: "stable"
ref: ${{ needs.verify-inputs.outputs.WORKING_BRANCH }}

check-measurements-reproducibility:
name: Check measurements reproducibility
needs: [os-image]
uses: ./.github/workflows/check-measurements-reproducibility.yml
with:
releasetag: ${{ inputs.version }}

update-hardcoded-measurements:
name: Update hardcoded measurements (in the CLI)
needs: [verify-inputs, os-image]
Expand Down
Loading