Files
cocos/pkg/attestation/gpu/collector.go
T
Jovan Djukic 27db9b29eb
CI / lint (push) Has been cancelled
CI / test (agent) (push) Has been cancelled
CI / test (cli) (push) Has been cancelled
CI / test (cmd) (push) Has been cancelled
CI / test (internal) (push) Has been cancelled
CI / test (manager, true) (push) Has been cancelled
CI / test (pkg) (push) Has been cancelled
CI / upload-coverage (push) Has been cancelled
COCOS-591: Add support for GPU CC attestation (#592)
* Added GPU evidence collection

* Added GPU evidence verification

* Added make command for nvattest helper

* Added command for installing all services

* changed attestion-service.service so it knows where the helper is

* Possible IGVM script bug

* Possible bug

* Bug

* bug

* Revert "bug"

This reverts commit d81d67e73d.

* Revert "Bug"

This reverts commit 5e566d53c1.

* Revert "Possible bug"

This reverts commit 47d13fe583.

* Revert "Possible IGVM script bug"

This reverts commit 3fb1b79537.

* Revert "changed attestion-service.service so it knows where the helper is"

This reverts commit f9f11ed183.

* Revert "Added command for installing all services"

This reverts commit 5dcf7a5c0a.

* NOISSUE - Enforce binding label check (#589)

* NOISSUE - Implement extensible resource downloader framework with support for S3, GCS, and OCI sources (#590)

* feat: implement extensible resource downloader framework with support for S3, GCS, and OCI sources

Signed-off-by: SammyOina <sammyoina@gmail.com>

* refactor: improve resource URL parsing and add support for bare OCI image references

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* fix: add empty string check and slash requirement for OCI image inference, and update python unit tests with event mock expectations

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* refactor: introduce OCIClient interface, add test coverage for decryption, and improve resource download error handling

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* chore: remove trailing whitespace in OCI downloader and HTTP tests

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

---------

Signed-off-by: SammyOina <sammyoina@gmail.com>
Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* Refactored baed on comments

* Added GPU evidence collection

* Added GPU evidence verification

* Added make command for nvattest helper

* Added command for installing all services

* changed attestion-service.service so it knows where the helper is

* Possible IGVM script bug

* Possible bug

* Bug

* bug

* Revert "bug"

This reverts commit d81d67e73d.

* Revert "Bug"

This reverts commit 5e566d53c1.

* Revert "Possible bug"

This reverts commit 47d13fe583.

* Revert "Possible IGVM script bug"

This reverts commit 3fb1b79537.

* Revert "changed attestion-service.service so it knows where the helper is"

This reverts commit f9f11ed183.

* Revert "Added command for installing all services"

This reverts commit 5dcf7a5c0a.

* Refactored baed on comments

* fixed lint error

* fixed tests

* Fixed according to comments

* COCOS-584 - Support multiple kbs (#587)

* feat: Implement per-resource KBS configuration, allowing algorithms and datasets to specify individual KBS URLs.

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* refactor: Encapsulate CLI error handling and CVM certificate paths within the CLI struct, and add algorithm type to agent's algorithm structure.

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* style: Remove blank lines and fix indentation in CLI commands.

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* refactor: Update downloadAndDecryptGenericResource to accept KBS URL as a parameter and adjust related tests

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* refactor: group CLI configuration into structured types and simplify skopeo decryption key handling

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

---------

Signed-off-by: Sammy Oina <sammyoina@gmail.com>

* Added GPU evidence collection

* Added GPU evidence verification

* Added make command for nvattest helper

* Added command for installing all services

* changed attestion-service.service so it knows where the helper is

* Possible IGVM script bug

* Possible bug

* Bug

* bug

* Revert "bug"

This reverts commit d81d67e73d.

* Revert "Bug"

This reverts commit 5e566d53c1.

* Revert "Possible bug"

This reverts commit 47d13fe583.

* Revert "Possible IGVM script bug"

This reverts commit 3fb1b79537.

* Revert "changed attestion-service.service so it knows where the helper is"

This reverts commit f9f11ed183.

* Revert "Added command for installing all services"

This reverts commit 5dcf7a5c0a.

* Refactored baed on comments

* Added GPU evidence collection

* Added GPU evidence verification

* Added make command for nvattest helper

* Added command for installing all services

* changed attestion-service.service so it knows where the helper is

* Possible IGVM script bug

* Possible bug

* Bug

* bug

* Revert "bug"

This reverts commit d81d67e73d.

* Revert "Bug"

This reverts commit 5e566d53c1.

* Revert "Possible bug"

This reverts commit 47d13fe583.

* Revert "Possible IGVM script bug"

This reverts commit 3fb1b79537.

* Revert "changed attestion-service.service so it knows where the helper is"

This reverts commit f9f11ed183.

* Revert "Added command for installing all services"

This reverts commit 5dcf7a5c0a.

* Refactored baed on comments

* fixed lint error

* fixed tests

* Fixed according to comments

---------

Signed-off-by: SammyOina <sammyoina@gmail.com>
Signed-off-by: Sammy Oina <sammyoina@gmail.com>
Co-authored-by: Danko Miladinovic <72250944+danko-miladinovic@users.noreply.github.com>
Co-authored-by: Sammy Kerata Oina <44265300+SammyOina@users.noreply.github.com>
2026-05-08 16:35:04 +02:00

139 lines
3.7 KiB
Go

// Copyright (c) Ultraviolet
// SPDX-License-Identifier: Apache-2.0
package gpu
import (
"bytes"
"context"
"encoding/hex"
"encoding/json"
"fmt"
"os/exec"
"strings"
"time"
)
const (
DefaultVendor = "nvidia"
DefaultEvidenceFormat = "nvat-json"
)
// Collector retrieves GPU evidence for the current attestation session.
type Collector interface {
Collect(ctx context.Context, nonce []byte) (*Evidence, error)
}
// Evidence contains low-level GPU evidence collected out-of-process.
type Evidence struct {
Vendor string
EvidenceFormat string
Nonce []byte
RawEvidence []byte
}
type commandCollector struct {
binaryPath string
timeout time.Duration
execCommandContext func(ctx context.Context, name string, arg ...string) *exec.Cmd
}
type helperRequest struct {
Mode string `json:"mode,omitempty"`
NonceHex string `json:"nonce_hex"`
EvidenceJSON json.RawMessage `json:"evidence_json,omitempty"`
}
type helperResponse struct {
Vendor string `json:"vendor,omitempty"`
EvidenceFormat string `json:"evidence_format,omitempty"`
EvidenceJSON json.RawMessage `json:"evidence_json,omitempty"`
ClaimsJSON json.RawMessage `json:"claims_json,omitempty"`
DetachedEATJSON json.RawMessage `json:"detached_eat_json,omitempty"`
}
// NewCommandCollector creates a collector that shells out to a helper binary.
// The helper is expected to read a JSON request on stdin and emit a JSON
// response on stdout. See tools/nvidia-attestation-helper for the contract.
func NewCommandCollector(binaryPath string, timeout time.Duration) (Collector, error) {
if strings.TrimSpace(binaryPath) == "" {
return nil, fmt.Errorf("gpu helper path cannot be empty")
}
if timeout <= 0 {
timeout = 30 * time.Second
}
return &commandCollector{
binaryPath: binaryPath,
timeout: timeout,
execCommandContext: exec.CommandContext,
}, nil
}
func (c *commandCollector) Collect(ctx context.Context, nonce []byte) (*Evidence, error) {
if len(nonce) == 0 {
return nil, fmt.Errorf("gpu nonce cannot be empty")
}
reqBody, err := json.Marshal(helperRequest{
Mode: "collect",
NonceHex: hex.EncodeToString(nonce),
})
if err != nil {
return nil, fmt.Errorf("failed to marshal GPU helper request: %w", err)
}
runCtx := ctx
cancel := func() {}
if c.timeout > 0 {
runCtx, cancel = context.WithTimeout(ctx, c.timeout)
}
defer cancel()
stdout := &bytes.Buffer{}
stderr := &bytes.Buffer{}
cmd := c.execCommandContext(runCtx, c.binaryPath)
cmd.Stdin = bytes.NewReader(reqBody)
cmd.Stdout = stdout
cmd.Stderr = stderr
if err := cmd.Run(); err != nil {
errMsg := strings.TrimSpace(stderr.String())
if errMsg == "" {
errMsg = err.Error()
}
return nil, fmt.Errorf("gpu helper failed: %s", errMsg)
}
var resp helperResponse
if err := json.Unmarshal(stdout.Bytes(), &resp); err != nil {
return nil, fmt.Errorf("failed to decode GPU helper response: %w", err)
}
if len(resp.EvidenceJSON) == 0 {
return nil, fmt.Errorf("gpu helper response did not contain evidence_json")
}
vendor := resp.Vendor
if vendor == "" {
vendor = DefaultVendor
}
evidenceFormat := resp.EvidenceFormat
if evidenceFormat == "" {
evidenceFormat = DefaultEvidenceFormat
}
return &Evidence{
Vendor: vendor,
EvidenceFormat: evidenceFormat,
Nonce: append([]byte(nil), nonce...),
RawEvidence: append([]byte(nil), resp.EvidenceJSON...),
}, nil
}
// SetExecCommandContext allows tests to inject a mock exec.CommandContext.
func (c *commandCollector) SetExecCommandContext(cmdFunc func(ctx context.Context, name string, arg ...string) *exec.Cmd) {
c.execCommandContext = cmdFunc
}