Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
19 changes: 19 additions & 0 deletions .github/workflows/_release-buildernet-image.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ on:
description: "R2 cache object name (e.g. 'cache' or 'cache-playground')"
type: string
required: true
portable-measurements:
description: "Generate portable measurements for the published GCP UKI"
type: boolean
default: true

jobs:
build:
Expand Down Expand Up @@ -131,6 +135,21 @@ jobs:
fi
mkosi "${ARGS[@]}"

- name: Install portable measurement tool
if: inputs.portable-measurements
uses: dtolnay/rust-toolchain@stable

- name: Generate portable measurements
if: inputs.portable-measurements
env:
ATTEST_REV: e7f59c78f9eabd5d1ac7c9e96da46027878d038c
run: |
cargo install --locked --git https://github.com/Easy-TEE/attest \
--rev "${ATTEST_REV}" --package attest-cli --no-default-features
make measure-portable \
UKI_FILE="mkosi.output/buildernet-gcp_${IMAGE_VERSION}.efi" \
MEASUREMENTS_FILE="mkosi.output/buildernet-${IMAGE_VERSION}-portable-measurements.json"

- name: Prepare cache
run: |
sudo find . \( -name "mkosi.builddir" -o -name "mkosi.cache" -o -name "mkosi.tools" \) -type d -print0 | \
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/release-playground.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,5 @@ jobs:
checksum-globs: "buildernet-*.qcow2"
r2-include: "buildernet-*.{qcow2,minisig,sha256}"
cache-name: "cache-playground"
portable-measurements: false
secrets: inherit
4 changes: 2 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
uses: ./.github/workflows/_release-buildernet-image.yml
with:
r2-path-prefix: "buildernet-images"
checksum-globs: "buildernet-*.{efi,tar.gz,vhd,qcow2}"
r2-include: "buildernet-*.{efi,tar.gz,vhd,qcow2,minisig,sha256}"
checksum-globs: "buildernet-*.{efi,tar.gz,vhd,qcow2,json}"
r2-include: "buildernet-*.{efi,tar.gz,vhd,qcow2,minisig,sha256,json}"
cache-name: "cache"
secrets: inherit
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@ tmp/
!/**/.gitkeep
.vscode/
CLAUDE.local.md
/.bypass-lima
10 changes: 9 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

SHELL := /usr/bin/env bash
WRAPPER := scripts/env_wrapper.sh
UKI_FILE ?= mkosi.output/buildernet-gcp_latest.efi
MEASUREMENTS_FILE ?= mkosi.output/portable_measurements.json

# Lima build VM name, mirroring scripts/env_wrapper.sh: tee-builder-<sha256(repo path)[:8]>.
ifndef LIMA_VM
Expand All @@ -21,7 +23,7 @@ help: ## display their help.

##@ Build

.PHONY: build build-dev build-local smoke boot clean clean-vm stop-vm
.PHONY: build build-dev build-local smoke measure-portable boot clean clean-vm stop-vm

build: ## build all BuilderNet images (azure, gcp, qemu)
$(WRAPPER) mkosi $(ARCH) --force -I buildernet.conf build
Expand All @@ -36,6 +38,12 @@ smoke: ## tiny quick image build to validate the toolchain
$(WRAPPER) mkosi -C tests/smoke --force build
@echo "Smoke build OK"

measure-portable: ## export portable measurements for the GCP UKI (override UKI_FILE=...)
@mkdir -p "$(dir $(MEASUREMENTS_FILE))"
@command -v attest >/dev/null || { echo "attest not found; install Easy-TEE/attest from main" >&2; exit 1; }
@attest measure portable --no-azure "$(UKI_FILE)" > "$(MEASUREMENTS_FILE)"
@echo "Portable measurements exported to $(MEASUREMENTS_FILE)"

##@ Run

boot: ## boot the built qemu UKI (no disk/TPM). root shell: `make console` in another terminal
Expand Down
68 changes: 34 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,47 +74,47 @@ To verify that our official images are built from the corresponding git revision
4. Calculate the SHA256 hashsum of the *.efi image in the `mkosi.output` directory. It should match the hashsum from the *.sha256 file from https://downloads.buildernet.org

# Measurements
Measurement are a way to verify that the image you built offline matches the one running as a VM.

To measure a Azure image:
1. Clone github.com/flashbots/measured-boot/ repo and build the `measured-boot` script
```
go build
```
2. Measure the image offline
```
./measured-boot image.efi /dev/null --direct-uki
Portable measurements let you verify that a BuilderNet GCP VM is running the OS image
you audited and built locally, without depending on GCP-specific TDX measurement values.

Build the images, install the `attest` CLI from
[`Easy-TEE/attest`](https://github.com/Easy-TEE/attest) `main` (pinned below to its current
head for reproducibility), and measure the GCP UKI:

```bash
make build
cargo install --locked --git https://github.com/Easy-TEE/attest \
--rev e7f59c78f9eabd5d1ac7c9e96da46027878d038c \
--package attest-cli --no-default-features
make measure-portable
```
3. Clone https://github.com/flashbots/attested-tls-proxy.git repo and run the `attested-get` tool

This writes `mkosi.output/portable_measurements.json`. To measure another UKI or choose a
different output path, set `UKI_FILE` or `MEASUREMENTS_FILE`:

```bash
make measure-portable \
UKI_FILE=mkosi.output/buildernet-gcp_2.9.1-deadbeef.efi \
MEASUREMENTS_FILE=mkosi.output/portable_measurements.json
```
git clone https://github.com/flashbots/attested-tls-proxy.git
cd attested-tls-proxy
curl -fSsL https://measurements.buildernet.org > /tmp/measurements-buildernet.json

For a release build, compare this file with the
`buildernet-<version>-portable-measurements.json` file published alongside the image.

To attest a running VM against those image hashes, build `attested-get` from
[`flashbots/attested-tls-proxy`](https://github.com/flashbots/attested-tls-proxy):

```bash
git clone https://github.com/flashbots/attested-tls-proxy
cd attested-tls-proxy
cargo run -- attested-get \
--measurements-file /tmp/measurements-buildernet.json \
https://_BUILDERNET_INSTANCE_:7936
--measurements-file ../flashbots-images/mkosi.output/portable_measurements.json \
https://<buildernet-instance>:7936
```
1. Compare PCRs 4 and 11 of the offline image and the deployed one, they should match.

To measure a GCP image:
1. Clone github.com/flashbots/dstack-mr-gcp repo and build the `dstack-mr` tool
```
go build
```
2. Measure the image offline
```
./dstack-mr -uki buildernet-gcp.efi
```
3. Clone github.com/flashbots/cvm-reverse-proxy repo and build the `attested-get` tool
```
go build cmd/attested-get/main.go
```
4. Measure the deployed image
```
./attested-get --addr=https://<instance IP>:7936
```
5. Compare PCRs 0-4 of the offline image and the deployed one, they should match.
Successful verification means the VM's attestation matches the hashes derived from your
locally built image.

# Development
- Use standard directory names of `mkosi` so that it can automatically pick it up.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ set -euo pipefail

echo "Installing attested-tls-proxy..."

VERSION="v1.1.2"
EXPECTED_SHA256=3b1b1868a5fcb1c0a0b07cfa32a76d2c609c99b9705596cc4a528659208d0349
VERSION="v2.0.1"
EXPECTED_SHA256=2c8f9f720a103f9d9cc1b53a0726b77f9310175057394cc4b2d5c565e49d849f
curl -sSfL https://github.com/flashbots/attested-tls-proxy/releases/download/${VERSION}/attested-tls-proxy_1.${VERSION}_amd64.deb \
-o $PACKAGEDIR/attested-tls-proxy.deb
echo "${EXPECTED_SHA256}" $PACKAGEDIR/attested-tls-proxy.deb | sha256sum --check
Loading