mirror of
https://github.com/luxfi/mpc.git
synced 2026-09-24 00:26:24 +00:00
v0.61 — wire the scheduler workload-policy gate into the MPC SignGate.
SignGate gains optional Scheduler + Worker fields; AuthorizeSign now
runs scheduler.Eligible(worker, ci.PolicyID) BEFORE the policy
verifier and short-circuits on insufficient trust posture. Existing
callers that pass nil Scheduler are unaffected.
pkg/scheduler/policy_gate.go — TrustMode/IOLevel enums,
WorkloadPolicy.Eligible(Worker)
pkg/scheduler/service_drain.go — AuthorizeDrain + AuthorizeSession
pkg/mpc/sign_orchestrator.go — Scheduler/Worker fields,
WithScheduler(...), two-stage gate
v0.62 — NVIDIA Confidential-Compute attestation primitives. Clean-room
parsers + verifiers against the publicly documented nvTrust schema
(Apache-2 derived); no NVIDIA proprietary code vendored.
pkg/attestation/nvidia/gpu_report.go — GPU evidence-report parser
pkg/attestation/nvidia/nras_client.go — NRAS HTTP client + JWS verify
pkg/attestation/nvidia/rim.go — RIM signature + value match
pkg/attestation/nvidia/composite.go — VerifiedBundle (CPU+GPU bind)
Tests (57 passing, -race clean):
pkg/scheduler — 11 (truth-table, drain,
session, orchestrator
integration)
pkg/attestation/nvidia — 46 (parser, RIM Ed25519/ECDSA/
RSA-PSS, NRAS happy/error/
signature paths, ECDSA JOSE)
pkg/attestation/nvidia (hwattest) — 3, env-skipped without real GPU
Sibling v0.60 reconciliation: pkg/registry + pkg/attestation already
land WorkerCapability + CompositeAttestation envelope using lattice
trust types. nvidia.VerifiedBundle is renamed (was Composite-) to
avoid collision with pkg/attestation.CompositeAttestation; the
canonical envelope wraps the verified blobs this package emits.
Residual: lattice/v7/types is not yet published, so pkg/registry +
pkg/attestation cannot compile against luxfi/[email protected]; the
sibling v0.60 work tracks that. pkg/policy still has a pre-existing
unresolved import of luxfi/fhe/threshold (should be /pkg/threshold);
sign_orchestrator_scheduler_test.go is ready to run as soon as that
upstream issue is fixed by its owner.
142 lines
3.8 KiB
Go
142 lines
3.8 KiB
Go
//go:build hwattest
|
|
|
|
// Real-hardware attestation tests. Build with `-tags hwattest` on a
|
|
// host with a Hopper (H100) or Blackwell (B100/B200) GPU plus the
|
|
// NVIDIA confidential-compute stack. The default build excludes this
|
|
// file so CI does not fault on hardware that is not present.
|
|
//
|
|
// Set environment:
|
|
//
|
|
// NRAS_ENDPOINT — full URL to NRAS (default: production NRAS)
|
|
// NRAS_TRUST_ROOT_PEM — path to a PEM file containing the NRAS
|
|
// signing public key
|
|
// GPU_REPORT_PATH — path to a JSON evidence report produced by
|
|
// the local nvidia-cc-host binary
|
|
// RIM_PATH — path to a signed RIM JSON for this driver
|
|
// and VBIOS combination
|
|
// RIM_TRUST_ROOT_PEM — path to a PEM file containing the RIM
|
|
// signing public key (may equal NRAS root)
|
|
//
|
|
// All tests skip when their inputs are missing — running with the
|
|
// build tag on a host that lacks a configured GPU is harmless.
|
|
|
|
package nvidia
|
|
|
|
import (
|
|
"context"
|
|
"crypto/x509"
|
|
"encoding/pem"
|
|
"os"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func loadPubKeyPEM(t *testing.T, path string) interface{} {
|
|
t.Helper()
|
|
if path == "" {
|
|
t.Skipf("PEM path not set")
|
|
}
|
|
raw, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatalf("read PEM %s: %v", path, err)
|
|
}
|
|
block, _ := pem.Decode(raw)
|
|
if block == nil {
|
|
t.Fatalf("no PEM block in %s", path)
|
|
}
|
|
pub, err := x509.ParsePKIXPublicKey(block.Bytes)
|
|
if err != nil {
|
|
t.Fatalf("parse PKIX %s: %v", path, err)
|
|
}
|
|
return pub
|
|
}
|
|
|
|
func TestHardware_ParseLocalGPUReport(t *testing.T) {
|
|
path := os.Getenv("GPU_REPORT_PATH")
|
|
if path == "" {
|
|
t.Skip("GPU_REPORT_PATH not set")
|
|
}
|
|
raw, err := os.ReadFile(path)
|
|
if err != nil {
|
|
t.Fatalf("read evidence: %v", err)
|
|
}
|
|
rep, err := ParseGPUReport(raw)
|
|
if err != nil {
|
|
t.Fatalf("parse evidence: %v", err)
|
|
}
|
|
if rep.Architecture != "Hopper" && rep.Architecture != "Blackwell" {
|
|
t.Fatalf("unexpected arch: %q", rep.Architecture)
|
|
}
|
|
t.Logf("parsed report: arch=%s driver=%s vbios=%s",
|
|
rep.Architecture, rep.DriverVersion, rep.VBIOSVersion)
|
|
}
|
|
|
|
func TestHardware_VerifyAgainstRealNRAS(t *testing.T) {
|
|
endpoint := os.Getenv("NRAS_ENDPOINT")
|
|
if endpoint == "" {
|
|
t.Skip("NRAS_ENDPOINT not set")
|
|
}
|
|
reportPath := os.Getenv("GPU_REPORT_PATH")
|
|
if reportPath == "" {
|
|
t.Skip("GPU_REPORT_PATH not set")
|
|
}
|
|
rootPath := os.Getenv("NRAS_TRUST_ROOT_PEM")
|
|
if rootPath == "" {
|
|
t.Skip("NRAS_TRUST_ROOT_PEM not set")
|
|
}
|
|
raw, err := os.ReadFile(reportPath)
|
|
if err != nil {
|
|
t.Fatalf("read evidence: %v", err)
|
|
}
|
|
rep, err := ParseGPUReport(raw)
|
|
if err != nil {
|
|
t.Fatalf("parse evidence: %v", err)
|
|
}
|
|
pub := loadPubKeyPEM(t, rootPath)
|
|
|
|
c := NewNRASClient(endpoint, []TrustRoot{{KeyID: "nras", Public: pub}})
|
|
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
|
defer cancel()
|
|
|
|
res, err := c.Verify(ctx, raw, rep.Nonce, VerifyOptions{})
|
|
if err != nil {
|
|
t.Fatalf("nras verify: %v", err)
|
|
}
|
|
if res.Token == "" {
|
|
t.Fatal("empty token")
|
|
}
|
|
}
|
|
|
|
func TestHardware_RIMMatchAgainstReport(t *testing.T) {
|
|
reportPath := os.Getenv("GPU_REPORT_PATH")
|
|
rimPath := os.Getenv("RIM_PATH")
|
|
rimRoot := os.Getenv("RIM_TRUST_ROOT_PEM")
|
|
if reportPath == "" || rimPath == "" || rimRoot == "" {
|
|
t.Skip("GPU_REPORT_PATH / RIM_PATH / RIM_TRUST_ROOT_PEM not all set")
|
|
}
|
|
rep, err := readReport(reportPath)
|
|
if err != nil {
|
|
t.Fatalf("read report: %v", err)
|
|
}
|
|
rimRaw, err := os.ReadFile(rimPath)
|
|
if err != nil {
|
|
t.Fatalf("read rim: %v", err)
|
|
}
|
|
pub := loadPubKeyPEM(t, rimRoot)
|
|
rim, err := ParseAndVerifyRIM(rimRaw, []TrustRoot{{KeyID: "rim", Public: pub}})
|
|
if err != nil {
|
|
t.Fatalf("rim parse+verify: %v", err)
|
|
}
|
|
if err := rim.Match(rep); err != nil {
|
|
t.Fatalf("rim match: %v", err)
|
|
}
|
|
}
|
|
|
|
func readReport(path string) (*GPUReport, error) {
|
|
raw, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return ParseGPUReport(raw)
|
|
}
|