Skip to content
Open
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
65 changes: 65 additions & 0 deletions .github/actions/publish-oras-artifact/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
name: Publish ORAS artifact
description: Package a binary and publish as ORAS artifact with manifest

inputs:
registry:
description: OCI registry hostname
required: true
image_name:
description: Repository image namespace
required: true
artifact_name:
description: Binary/artifact name
required: true
rust_target:
description: Rust target triple
required: true
git_sha:
description: Git SHA for tag
required: true
tee:
description: TEE platform suffix for tag
required: true
arch:
description: Build architecture (x86_64/aarch64/powerpc64le/...)
required: true
oci_arch:
description: OCI architecture for manifest annotation
required: true

outputs:
image:
description: Published image name
value: ${{ steps.publish.outputs.image }}
digest:
description: Published image digest
value: ${{ steps.publish.outputs.digest }}

runs:
using: composite
steps:
- id: publish
shell: bash
run: |
mkdir -p oras
cd oras
cp ../target/${{ inputs.rust_target }}/release/${{ inputs.artifact_name }} .
tar cJf "${{ inputs.artifact_name }}.tar.xz" "${{ inputs.artifact_name }}"

arch="${{ inputs.arch }}"
# Align non-standard Rust arch naming with OCI conventions.
[ "$arch" = "powerpc64le" ] && arch="ppc64le"

arch_tag="${{ inputs.git_sha }}-${{ inputs.tee }}_${arch}"
image="${{ inputs.registry }}/${{ inputs.image_name }}/${{ inputs.artifact_name }}"
tag="${{ inputs.git_sha }}-${{ inputs.tee }}"

oras push "${image}:${arch_tag}" "${{ inputs.artifact_name }}.tar.xz"
docker manifest create "${image}:${tag}" --amend "${image}:${arch_tag}"
docker manifest annotate --arch "${{ inputs.oci_arch }}" --os linux "${image}:${tag}" "${image}:${arch_tag}"
docker manifest push "${image}:${tag}"

# add image and digest to output for attestation
echo "image=${image}" >> "$GITHUB_OUTPUT"
digest="$(oras manifest fetch "${image}:${arch_tag}" --descriptor | jq -r .digest)"
echo "digest=${digest}" >> "$GITHUB_OUTPUT"
59 changes: 33 additions & 26 deletions .github/workflows/publish-artifacts.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ permissions:
contents: read

jobs:
publish-aa:
publish-aa-and-initdata-validator:
permissions:
contents: read
packages: write
Expand Down Expand Up @@ -70,45 +70,52 @@ jobs:

- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Build AA
- name: Build AA and Initdata Validator
env:
ARCH: ${{ matrix.platform.arch }}
LIBC: ${{ matrix.platform.libc }}
run: |
make ./target/${{ env.RUST_TARGET }}/release/attestation-agent
make ./target/${{ env.RUST_TARGET }}/release/initdata-validator

- name: Publish with ORAS
- name: Publish AA with ORAS
id: publish
env:
OCI_ARCH: ${{ matrix.platform.arch == 'x86_64' && 'amd64' || matrix.platform.arch == 'aarch64' && 'arm64' || matrix.platform.arch == 'powerpc64le' && 'ppc64le' || matrix.platform.arch }}
run: |
mkdir oras
cd oras
cp ../target/${{ env.RUST_TARGET }}/release/attestation-agent .
tar cJf attestation-agent.tar.xz attestation-agent
arch="${{ matrix.platform.arch }}"
# After building for target powerpc64le, tag and push the image as ppc64le to match standard arch naming.
[ "$arch" = "powerpc64le" ] && arch="ppc64le"
arch_tag="${{ github.sha }}-${{ matrix.platform.tee }}_${arch}"
image="${REGISTRY}/${IMAGE_NAME}/attestation-agent"
tag="${{ github.sha }}-${{ matrix.platform.tee }}"
oras push "${image}:${arch_tag}" attestation-agent.tar.xz
# We need to create the platform annotations with docker, since oras 1.2 doesn't support
# pushing with platform yet.
docker manifest create "${image}:${tag}" --amend "${image}:${arch_tag}"
docker manifest annotate --arch "$OCI_ARCH" --os linux "${image}:${tag}" "${image}:${arch_tag}"
docker manifest push "${image}:${tag}"
# add image and digest to output for attestation
echo "image=${image}" >> "$GITHUB_OUTPUT"
digest="$(oras manifest fetch "${image}:${arch_tag}" --descriptor | jq -r .digest)"
echo "digest=${digest}" >> "$GITHUB_OUTPUT"
uses: ./.github/actions/publish-oras-artifact
with:
registry: ${{ env.REGISTRY }}
image_name: ${{ env.IMAGE_NAME }}
artifact_name: attestation-agent
rust_target: ${{ env.RUST_TARGET }}
git_sha: ${{ github.sha }}
tee: ${{ matrix.platform.tee }}
arch: ${{ matrix.platform.arch }}
oci_arch: ${{ matrix.platform.arch == 'x86_64' && 'amd64' || matrix.platform.arch == 'aarch64' && 'arm64' || matrix.platform.arch == 'powerpc64le' && 'ppc64le' || matrix.platform.arch }}

- name: Publish Initdata Validator with ORAS
id: publish-initdata-validator
uses: ./.github/actions/publish-oras-artifact
with:
registry: ${{ env.REGISTRY }}
image_name: ${{ env.IMAGE_NAME }}
artifact_name: initdata-validator
rust_target: ${{ env.RUST_TARGET }}
git_sha: ${{ github.sha }}
tee: ${{ matrix.platform.tee }}
arch: ${{ matrix.platform.arch }}
oci_arch: ${{ matrix.platform.arch == 'x86_64' && 'amd64' || matrix.platform.arch == 'aarch64' && 'arm64' || matrix.platform.arch == 'powerpc64le' && 'ppc64le' || matrix.platform.arch }}

- uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
with:
subject-name: ${{ steps.publish.outputs.image }}
subject-digest: ${{ steps.publish.outputs.digest }}
push-to-registry: true

- uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
with:
subject-name: ${{ steps.publish-initdata-validator.outputs.image }}
subject-digest: ${{ steps.publish-initdata-validator.outputs.digest }}
push-to-registry: true

publish-cdh-and-asr:
permissions:
contents: read
Expand Down
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -74,12 +74,15 @@ endif
CDH := confidential-data-hub
AA := attestation-agent
ASR := api-server-rest
ATTESTER_DIR := attester
INITDATA_VALIDATOR := initdata-validator

BUILD_DIR := target/$(ARCH)-unknown-linux-$(LIBC)/release

CDH_BINARY := $(BUILD_DIR)/$(CDH)
AA_BINARY := $(BUILD_DIR)/$(AA)
ASR_BINARY := $(BUILD_DIR)/$(ASR)
INITDATA_VALIDATOR_BINARY := $(BUILD_DIR)/$(INITDATA_VALIDATOR)

build: $(CDH_BINARY) $(ASR_BINARY) $(AA_BINARY)
@echo guest components built for $(TEE_PLATFORM) succeeded!
Expand All @@ -92,6 +95,10 @@ $(AA_BINARY):
@echo build $(AA) for $(TEE_PLATFORM)
cd $(AA) && $(MAKE) ttrpc=true ARCH=$(ARCH) LIBC=$(LIBC) ATTESTER=$(ATTESTER)

$(INITDATA_VALIDATOR_BINARY):
@echo build $(INITDATA_VALIDATOR) for $(TEE_PLATFORM)
cd $(AA)/$(ATTESTER_DIR) && $(MAKE) ARCH=$(ARCH) LIBC=$(LIBC) ATTESTER=$(ATTESTER)

$(ASR_BINARY):
@echo build $(ASR) for $(TEE_PLATFORM)
cd $(ASR) && $(MAKE) ARCH=$(ARCH) LIBC=$(LIBC)
Expand Down
4 changes: 4 additions & 0 deletions attestation-agent/attester/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,10 @@ rstest.workspace = true
name = "evidence_getter"
required-features = ["bin"]

[[bin]]
name = "initdata-validator"
required-features = ["bin"]

[features]
default = ["all-attesters"]
all-attesters = [
Expand Down
26 changes: 26 additions & 0 deletions attestation-agent/attester/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
ARCH ?= $(shell uname -m)
LIBC ?= gnu
ATTESTER ?=
DEBUG ?=

TARGET_DIR := ../../target/$(ARCH)-unknown-linux-$(LIBC)
BIN_NAME := initdata-validator

features := bin
ifdef ATTESTER
ifneq ($(ATTESTER), none)
features += ,$(ATTESTER)
endif
else
features += ,all-attesters
endif

ifdef DEBUG
release :=
else
release := --release
endif

build:
@echo build $(BIN_NAME)
cargo build $(release) --no-default-features --features "$(features)" --bin $(BIN_NAME) --target $(ARCH)-unknown-linux-$(LIBC)
39 changes: 39 additions & 0 deletions attestation-agent/attester/src/bin/initdata-validator.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// Copyright (c) 2026 Alibaba Cloud
//
// SPDX-License-Identifier: Apache-2.0
//

use anyhow::{Context, Result};
use attester::{detect_tee_type, BoxedAttester, InitDataResult};
use base64::{engine::general_purpose::URL_SAFE_NO_PAD, Engine as _};
use clap::Parser;

#[derive(Debug, Parser)]
#[command(author)]
struct Cli {
/// URL_SAFE_NO_PAD base64 encoded initdata digest.
initdata: String,
}

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
let cli = Cli::parse();
let initdata = URL_SAFE_NO_PAD
.decode(cli.initdata.as_bytes())
.context("failed to decode initdata as URL_SAFE_NO_PAD base64")?;

let tee = detect_tee_type();
let attester = TryInto::<BoxedAttester>::try_into(tee)
.context("failed to initialize attester for current platform")?;

match attester
.bind_init_data(&initdata)
.await
.context("failed to bind initdata")?
{
InitDataResult::Ok => println!("initdata bind success: {tee:?}"),
InitDataResult::Unsupported => println!("initdata binding is unsupported on {tee:?}"),
}

Ok(())
}
Loading