Skip to content

Commit 04c78f9

Browse files
authored
Merge pull request #115 from nearai/feat/nv-attestation-sdk-evidence
feat: opt-in nv-attestation-sdk Rust bindings for GPU evidence
2 parents 7ddac37 + bb6f542 commit 04c78f9

7 files changed

Lines changed: 371 additions & 9 deletions

File tree

Cargo.lock

Lines changed: 67 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,19 @@ tracing-subscriber = { version = "0.3", features = ["env-filter", "json"] }
5858
metrics = "0.24"
5959
metrics-exporter-prometheus = "0.18"
6060

61+
[dependencies.nv-attestation-sdk]
62+
git = "https://github.com/NVIDIA/attestation-sdk.git"
63+
tag = "2026.04.29"
64+
optional = true
65+
66+
[features]
67+
# Enable the NVIDIA Attestation SDK Rust bindings as the GPU evidence
68+
# collection backend. Requires `libnvat.so.1` (and bindgen's clang) at
69+
# build time and the same shared library at runtime. When disabled
70+
# (default), evidence collection uses the existing Python subprocess
71+
# path. See `attestation_sdk.rs` for the runtime toggle.
72+
nv-attestation-sdk = ["dep:nv-attestation-sdk"]
73+
6174
[dev-dependencies]
6275
wiremock = "0.6"
6376
tower = { version = "0.5", features = ["util"] }

Dockerfile

Lines changed: 90 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,83 @@
1+
# Build args:
2+
# ENABLE_NV_ATTESTATION_SDK=1 → build with the nv-attestation-sdk Cargo
3+
# feature, link against libnvat.so for direct-FFI GPU evidence
4+
# collection (no Python subprocess). The runtime image is also
5+
# provisioned with libnvat.so. Default off until staging validates.
6+
# Even at "1" the runtime path stays Python-backed unless the env
7+
# var USE_NV_ATTESTATION_SDK=true is set on the container.
8+
# LIBNVAT_VERSION → exact apt-pinned version of NVIDIA's libnvat package
9+
# (see https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/).
10+
# The trailing ".<timestamp>-1" suffix is part of the upstream version
11+
# string and changes per build; pin it so rebuilds stay reproducible.
12+
ARG ENABLE_NV_ATTESTATION_SDK=0
13+
ARG LIBNVAT_VERSION=1.2.1.1777487608-1
14+
15+
# ─────────────────────────────────────────────────────────────────────
116
# Stage 1: Build the Rust binary
2-
FROM rust:1.93.0-bookworm AS builder
17+
#
18+
# Switched from rust:1.93.0-bookworm (Debian 12) to ubuntu:22.04 +
19+
# rustup so the libnvat we link against is the same .deb the runtime
20+
# image installs (NVIDIA only publishes libnvat for Ubuntu 22.04/24.04;
21+
# no Debian 12 build). Matching distributions on both sides eliminates
22+
# any libssl3/libcurl4/libxml2 ABI risk.
23+
# ─────────────────────────────────────────────────────────────────────
24+
FROM ubuntu:22.04 AS builder
25+
ARG ENABLE_NV_ATTESTATION_SDK
26+
ARG LIBNVAT_VERSION
27+
28+
ENV DEBIAN_FRONTEND=noninteractive
29+
30+
RUN apt-get update && apt-get install -y --no-install-recommends \
31+
ca-certificates curl git pkg-config build-essential gcc \
32+
libssl-dev \
33+
&& rm -rf /var/lib/apt/lists/*
34+
35+
# Install Rust 1.93.0 (matching the previous rust:1.93.0-bookworm base).
36+
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs \
37+
| sh -s -- -y --default-toolchain 1.93.0 --profile minimal --no-modify-path
38+
ENV PATH=/root/.cargo/bin:$PATH
339

4-
RUN apt-get update && apt-get install -y --no-install-recommends git pkg-config \
5-
&& rm -rf /var/lib/apt/lists/* /var/log/* /var/cache/ldconfig/aux-cache
40+
# Install libnvat-dev (headers + .so symlink) and libclang for bindgen
41+
# only when the SDK feature is on. -dev pulls in libnvat (the runtime
42+
# .so) as a versioned dependency, plus libcurl4/libxml2/libxmlsec1-openssl
43+
# which libnvat dynamically links against.
44+
RUN if [ "$ENABLE_NV_ATTESTATION_SDK" = "1" ]; then \
45+
set -e && \
46+
apt-get update && apt-get install -y --no-install-recommends wget gnupg && \
47+
wget -q https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb && \
48+
dpkg -i cuda-keyring_1.1-1_all.deb && rm cuda-keyring_1.1-1_all.deb && \
49+
apt-get update && apt-get install -y --no-install-recommends \
50+
clang libclang-dev \
51+
"libnvat-dev=${LIBNVAT_VERSION}" "libnvat=${LIBNVAT_VERSION}" && \
52+
ldconfig && \
53+
rm -rf /var/lib/apt/lists/* ; \
54+
fi
55+
56+
# Tell nv-attestation-sdk-sys's build.rs to look for the system-installed
57+
# libnvat (/usr/include/nvat.h + /usr/lib/.../libnvat.so) rather than
58+
# trying to build the C++ SDK from a sibling source directory. No-op when
59+
# the Cargo feature is disabled.
60+
ENV NVAT_USE_SYSTEM_LIB=1
661

762
WORKDIR /build
863

964
ARG SOURCE_DATE_EPOCH=0
1065
ENV SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH}
1166

67+
# Resolve the cargo feature flag once so dependency-cache and real builds
68+
# agree on the feature set.
69+
RUN if [ "$ENABLE_NV_ATTESTATION_SDK" = "1" ]; then \
70+
echo "--features nv-attestation-sdk" > /tmp/cargo-features; \
71+
else \
72+
: > /tmp/cargo-features; \
73+
fi
74+
1275
# Cache dependencies: copy manifests first, then do a dummy build
1376
COPY Cargo.toml Cargo.lock ./
14-
RUN mkdir src && echo "fn main() {}" > src/main.rs && echo "" > src/lib.rs \
77+
RUN FEATURES=$(cat /tmp/cargo-features) && \
78+
mkdir src && echo "fn main() {}" > src/main.rs && echo "" > src/lib.rs \
1579
&& mkdir -p benches && echo "fn main() {}" > benches/hot_path.rs && echo "fn main() {}" > benches/e2e.rs \
16-
&& cargo build --release --locked 2>/dev/null || true \
80+
&& cargo build --release --locked $FEATURES 2>/dev/null || true \
1781
&& rm -rf src benches \
1882
&& rm -f target/release/deps/*vllm_proxy_rs* \
1983
&& rm -f target/release/vllm-proxy-rs* \
@@ -22,19 +86,37 @@ RUN mkdir src && echo "fn main() {}" > src/main.rs && echo "" > src/lib.rs \
2286
# Copy real source and build — touch to ensure cargo detects changes
2387
COPY src/ src/
2488
COPY benches/ benches/
25-
RUN find src -name '*.rs' -exec touch {} + && cargo build --release --locked
89+
RUN FEATURES=$(cat /tmp/cargo-features) && \
90+
find src -name '*.rs' -exec touch {} + && cargo build --release --locked $FEATURES
2691

92+
# ─────────────────────────────────────────────────────────────────────
2793
# Stage 2: Runtime image
28-
# GPU attestation requires pynvml (needs CUDA), so use vllm base image
94+
# ─────────────────────────────────────────────────────────────────────
2995
FROM vllm/vllm-openai@sha256:014a95f21c9edf6abe0aea6b07353f96baa4ec291c427bb1176dc7c93a85845c
96+
ARG ENABLE_NV_ATTESTATION_SDK
97+
ARG LIBNVAT_VERSION
3098

3199
ENV PYTHONUNBUFFERED=1
32100

33101
# Install the verifier packages needed for GPU attestation evidence
34102
# nv-attestation-sdk provides the `verifier` module for GPU evidence collection
35-
# nv-ppcie-verifier is additionally needed for PPCIE multi-GPU systems
103+
# nv-ppcie-verifier is additionally needed for PPCIE multi-GPU systems.
104+
# When ENABLE_NV_ATTESTATION_SDK=1 these are still installed for the
105+
# Python fallback path (USE_NV_ATTESTATION_SDK=false at runtime); a
106+
# follow-up will drop them once the SDK path proves out.
36107
RUN pip install --no-cache-dir nv-attestation-sdk nv-ppcie-verifier
37108

109+
# Install libnvat (runtime) when the feature is built. vllm/vllm-openai
110+
# already has the CUDA apt repo configured, so cuda-keyring isn't needed
111+
# here. apt pulls in libcurl4/libxml2/libxmlsec1-openssl as deps.
112+
RUN if [ "$ENABLE_NV_ATTESTATION_SDK" = "1" ]; then \
113+
set -e && \
114+
apt-get update && apt-get install -y --no-install-recommends \
115+
"libnvat=${LIBNVAT_VERSION}" && \
116+
ldconfig && \
117+
rm -rf /var/lib/apt/lists/* ; \
118+
fi
119+
38120
WORKDIR /app
39121

40122
# Copy compiled binary and GPU evidence worker from builder

deny.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,9 @@ wildcards = "allow"
4848
[sources]
4949
unknown-registry = "deny"
5050
unknown-git = "deny"
51+
allow-git = [
52+
# NVIDIA's attestation SDK Rust bindings (libnvat FFI). Not yet on
53+
# crates.io; pinned to release tag 2026.04.29 in Cargo.toml. Optional
54+
# `nv-attestation-sdk` feature only — default builds don't pull this.
55+
"https://github.com/NVIDIA/attestation-sdk.git",
56+
]

src/attestation.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -976,7 +976,18 @@ async fn collect_gpu_evidence_with_nonce_check(
976976
tokio::time::sleep(std::time::Duration::from_millis(delay_ms)).await;
977977
}
978978

979-
let evidence = if let Some(cache) = cache {
979+
// Three backends, in priority order:
980+
// 1. nv-attestation-sdk (Rust → C FFI, opt-in via env var)
981+
// 2. cache's persistent Python worker (existing default)
982+
// 3. one-shot Python subprocess (fallback when no cache)
983+
// The self-check + retry below applies regardless of which one
984+
// produced the evidence.
985+
let evidence = if crate::attestation_sdk::is_active() && !gpu_no_hw_mode {
986+
// SDK path doesn't support no_gpu_mode (it requires real
987+
// hardware via NVML); fall back to the Python paths for
988+
// dev/test environments without GPUs.
989+
crate::attestation_sdk::collect_gpu_evidence_via_sdk(nonce_hex).await?
990+
} else if let Some(cache) = cache {
980991
cache
981992
.collect_gpu_evidence(nonce_hex, gpu_no_hw_mode)
982993
.await?

0 commit comments

Comments
 (0)