From f77ec5644a51f739f3b48290849e8f77ac7e450e Mon Sep 17 00:00:00 2001 From: Sammy Kerata Oina <44265300+SammyOina@users.noreply.github.com> Date: Thu, 19 Feb 2026 14:08:13 +0300 Subject: [PATCH] NOISSUE - Allow interoperability with CC Attestation Agent (#568) * feat: Add Confidential Containers attestation agent as an alternative attestation backend with new proto definitions and build system integration. Signed-off-by: Sammy Oina * fix: Update protoc-gen-go and protoc-gen-go-grpc versions in CI workflow Signed-off-by: Sammy Oina * feat: Add mock implementation for AttestationAgentServiceClient and corresponding tests Signed-off-by: Sammy Oina * fix: Add missing periods to test function comments in provider_test.go Signed-off-by: Sammy Oina --------- Signed-off-by: Sammy Oina --- .github/workflows/checkproto.yaml | 4 +- .mockery.yml | 7 + Makefile | 1 + agent/agent.pb.go | 2 +- agent/agent_grpc.pb.go | 16 +- agent/cvms/cvms.pb.go | 2 +- agent/cvms/cvms_grpc.pb.go | 6 +- agent/events/events.pb.go | 2 +- agent/log/log.pb.go | 2 +- agent/log/log_grpc.pb.go | 8 +- agent/runner/runner.pb.go | 2 +- agent/runner/runner_grpc.pb.go | 8 +- cmd/attestation-service/main.go | 70 +- hal/linux/Config.in | 2 + hal/linux/configs/cocos_defconfig | 4 + .../package/attestation-service/Config.in | 42 +- .../package/cc-attestation-agent/Config.in | 31 + .../cc-attestation-agent-setup.sh | 5 + .../cc-attestation-agent.mk | 37 + .../cc-attestation-agent.service | 13 + init/systemd/attestation-service.service | 5 + .../attestation-agent/attestation-agent.pb.go | 687 ++++++++++++++++++ .../attestation-agent/attestation-agent.proto | 73 ++ .../attestation-agent_grpc.pb.go | 312 ++++++++ .../mocks/attestationagentserviceclient.go | 565 ++++++++++++++ .../proto/attestation/v1/attestation.pb.go | 2 +- .../attestation/v1/attestation_grpc.pb.go | 8 +- manager/manager.pb.go | 2 +- manager/manager_grpc.pb.go | 12 +- pkg/attestation/ccaa/provider.go | 131 ++++ pkg/attestation/ccaa/provider_test.go | 325 +++++++++ 31 files changed, 2325 insertions(+), 61 deletions(-) create mode 100644 hal/linux/package/cc-attestation-agent/Config.in create mode 100644 hal/linux/package/cc-attestation-agent/cc-attestation-agent-setup.sh create mode 100644 hal/linux/package/cc-attestation-agent/cc-attestation-agent.mk create mode 100644 hal/linux/package/cc-attestation-agent/cc-attestation-agent.service create mode 100644 internal/proto/attestation-agent/attestation-agent.pb.go create mode 100644 internal/proto/attestation-agent/attestation-agent.proto create mode 100644 internal/proto/attestation-agent/attestation-agent_grpc.pb.go create mode 100644 internal/proto/attestation-agent/mocks/attestationagentserviceclient.go create mode 100644 pkg/attestation/ccaa/provider.go create mode 100644 pkg/attestation/ccaa/provider_test.go diff --git a/.github/workflows/checkproto.yaml b/.github/workflows/checkproto.yaml index fcb013a0..e980d562 100644 --- a/.github/workflows/checkproto.yaml +++ b/.github/workflows/checkproto.yaml @@ -35,8 +35,8 @@ jobs: - name: Set up protoc run: | PROTOC_VERSION=33.1 - PROTOC_GEN_VERSION=v1.36.8 - PROTOC_GRPC_VERSION=v1.5.1 + PROTOC_GEN_VERSION=v1.36.11 + PROTOC_GRPC_VERSION=v1.6.0 # Download and install protoc PROTOC_ZIP=protoc-$PROTOC_VERSION-linux-x86_64.zip diff --git a/.mockery.yml b/.mockery.yml index 003f2253..14553567 100644 --- a/.mockery.yml +++ b/.mockery.yml @@ -153,3 +153,10 @@ packages: dir: '{{.InterfaceDir}}/mocks' structname: '{{.InterfaceName}}' filename: "{{.InterfaceName | lower}}.go" + github.com/ultravioletrs/cocos/internal/proto/attestation-agent: + interfaces: + AttestationAgentServiceClient: + config: + dir: '{{.InterfaceDir}}/mocks' + structname: '{{.InterfaceName}}' + filename: "{{.InterfaceName | lower}}.go" diff --git a/Makefile b/Makefile index 7f0d8b33..a4e6bb06 100644 --- a/Makefile +++ b/Makefile @@ -41,6 +41,7 @@ protoc: protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative agent/events/events.proto protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative agent/cvms/cvms.proto protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative internal/proto/attestation/v1/attestation.proto + protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative internal/proto/attestation-agent/attestation-agent.proto protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative agent/log/log.proto protoc -I. --go_out=. --go_opt=paths=source_relative --go-grpc_out=. --go-grpc_opt=paths=source_relative agent/runner/runner.proto diff --git a/agent/agent.pb.go b/agent/agent.pb.go index c945c448..7cb06119 100644 --- a/agent/agent.pb.go +++ b/agent/agent.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.8 +// protoc-gen-go v1.36.11 // protoc v6.33.1 // source: agent/agent.proto diff --git a/agent/agent_grpc.pb.go b/agent/agent_grpc.pb.go index 0d7a7d1b..58350931 100644 --- a/agent/agent_grpc.pb.go +++ b/agent/agent_grpc.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.5.1 +// - protoc-gen-go-grpc v1.6.0 // - protoc v6.33.1 // source: agent/agent.proto @@ -164,22 +164,22 @@ type AgentServiceServer interface { type UnimplementedAgentServiceServer struct{} func (UnimplementedAgentServiceServer) Algo(grpc.ClientStreamingServer[AlgoRequest, AlgoResponse]) error { - return status.Errorf(codes.Unimplemented, "method Algo not implemented") + return status.Error(codes.Unimplemented, "method Algo not implemented") } func (UnimplementedAgentServiceServer) Data(grpc.ClientStreamingServer[DataRequest, DataResponse]) error { - return status.Errorf(codes.Unimplemented, "method Data not implemented") + return status.Error(codes.Unimplemented, "method Data not implemented") } func (UnimplementedAgentServiceServer) Result(*ResultRequest, grpc.ServerStreamingServer[ResultResponse]) error { - return status.Errorf(codes.Unimplemented, "method Result not implemented") + return status.Error(codes.Unimplemented, "method Result not implemented") } func (UnimplementedAgentServiceServer) Attestation(*AttestationRequest, grpc.ServerStreamingServer[AttestationResponse]) error { - return status.Errorf(codes.Unimplemented, "method Attestation not implemented") + return status.Error(codes.Unimplemented, "method Attestation not implemented") } func (UnimplementedAgentServiceServer) IMAMeasurements(*IMAMeasurementsRequest, grpc.ServerStreamingServer[IMAMeasurementsResponse]) error { - return status.Errorf(codes.Unimplemented, "method IMAMeasurements not implemented") + return status.Error(codes.Unimplemented, "method IMAMeasurements not implemented") } func (UnimplementedAgentServiceServer) AzureAttestationToken(context.Context, *AttestationTokenRequest) (*AttestationTokenResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method AzureAttestationToken not implemented") + return nil, status.Error(codes.Unimplemented, "method AzureAttestationToken not implemented") } func (UnimplementedAgentServiceServer) mustEmbedUnimplementedAgentServiceServer() {} func (UnimplementedAgentServiceServer) testEmbeddedByValue() {} @@ -192,7 +192,7 @@ type UnsafeAgentServiceServer interface { } func RegisterAgentServiceServer(s grpc.ServiceRegistrar, srv AgentServiceServer) { - // If the following call pancis, it indicates UnimplementedAgentServiceServer was + // If the following call panics, it indicates UnimplementedAgentServiceServer was // embedded by pointer and is nil. This will cause panics if an // unimplemented method is ever invoked, so we test this at initialization // time to prevent it from happening at runtime later due to I/O. diff --git a/agent/cvms/cvms.pb.go b/agent/cvms/cvms.pb.go index c928216d..1b0bb35b 100644 --- a/agent/cvms/cvms.pb.go +++ b/agent/cvms/cvms.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.8 +// protoc-gen-go v1.36.11 // protoc v6.33.1 // source: agent/cvms/cvms.proto diff --git a/agent/cvms/cvms_grpc.pb.go b/agent/cvms/cvms_grpc.pb.go index 749ea770..6b380df5 100644 --- a/agent/cvms/cvms_grpc.pb.go +++ b/agent/cvms/cvms_grpc.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.5.1 +// - protoc-gen-go-grpc v1.6.0 // - protoc v6.33.1 // source: agent/cvms/cvms.proto @@ -69,7 +69,7 @@ type ServiceServer interface { type UnimplementedServiceServer struct{} func (UnimplementedServiceServer) Process(grpc.BidiStreamingServer[ClientStreamMessage, ServerStreamMessage]) error { - return status.Errorf(codes.Unimplemented, "method Process not implemented") + return status.Error(codes.Unimplemented, "method Process not implemented") } func (UnimplementedServiceServer) mustEmbedUnimplementedServiceServer() {} func (UnimplementedServiceServer) testEmbeddedByValue() {} @@ -82,7 +82,7 @@ type UnsafeServiceServer interface { } func RegisterServiceServer(s grpc.ServiceRegistrar, srv ServiceServer) { - // If the following call pancis, it indicates UnimplementedServiceServer was + // If the following call panics, it indicates UnimplementedServiceServer was // embedded by pointer and is nil. This will cause panics if an // unimplemented method is ever invoked, so we test this at initialization // time to prevent it from happening at runtime later due to I/O. diff --git a/agent/events/events.pb.go b/agent/events/events.pb.go index 6e1be4f1..f52aba5d 100644 --- a/agent/events/events.pb.go +++ b/agent/events/events.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.8 +// protoc-gen-go v1.36.11 // protoc v6.33.1 // source: agent/events/events.proto diff --git a/agent/log/log.pb.go b/agent/log/log.pb.go index 0b4e405d..c822e1d1 100644 --- a/agent/log/log.pb.go +++ b/agent/log/log.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.8 +// protoc-gen-go v1.36.11 // protoc v6.33.1 // source: agent/log/log.proto diff --git a/agent/log/log_grpc.pb.go b/agent/log/log_grpc.pb.go index 41bf2d4a..2aaa7b51 100644 --- a/agent/log/log_grpc.pb.go +++ b/agent/log/log_grpc.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.5.1 +// - protoc-gen-go-grpc v1.6.0 // - protoc v6.33.1 // source: agent/log/log.proto @@ -80,10 +80,10 @@ type LogCollectorServer interface { type UnimplementedLogCollectorServer struct{} func (UnimplementedLogCollectorServer) SendLog(context.Context, *LogEntry) (*emptypb.Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method SendLog not implemented") + return nil, status.Error(codes.Unimplemented, "method SendLog not implemented") } func (UnimplementedLogCollectorServer) SendEvent(context.Context, *EventEntry) (*emptypb.Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method SendEvent not implemented") + return nil, status.Error(codes.Unimplemented, "method SendEvent not implemented") } func (UnimplementedLogCollectorServer) mustEmbedUnimplementedLogCollectorServer() {} func (UnimplementedLogCollectorServer) testEmbeddedByValue() {} @@ -96,7 +96,7 @@ type UnsafeLogCollectorServer interface { } func RegisterLogCollectorServer(s grpc.ServiceRegistrar, srv LogCollectorServer) { - // If the following call pancis, it indicates UnimplementedLogCollectorServer was + // If the following call panics, it indicates UnimplementedLogCollectorServer was // embedded by pointer and is nil. This will cause panics if an // unimplemented method is ever invoked, so we test this at initialization // time to prevent it from happening at runtime later due to I/O. diff --git a/agent/runner/runner.pb.go b/agent/runner/runner.pb.go index 68c30a09..32e7725f 100644 --- a/agent/runner/runner.pb.go +++ b/agent/runner/runner.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.8 +// protoc-gen-go v1.36.11 // protoc v6.33.1 // source: agent/runner/runner.proto diff --git a/agent/runner/runner_grpc.pb.go b/agent/runner/runner_grpc.pb.go index 4ec12046..4bdc9d2d 100644 --- a/agent/runner/runner_grpc.pb.go +++ b/agent/runner/runner_grpc.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.5.1 +// - protoc-gen-go-grpc v1.6.0 // - protoc v6.33.1 // source: agent/runner/runner.proto @@ -80,10 +80,10 @@ type ComputationRunnerServer interface { type UnimplementedComputationRunnerServer struct{} func (UnimplementedComputationRunnerServer) Run(context.Context, *RunRequest) (*RunResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method Run not implemented") + return nil, status.Error(codes.Unimplemented, "method Run not implemented") } func (UnimplementedComputationRunnerServer) Stop(context.Context, *StopRequest) (*emptypb.Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method Stop not implemented") + return nil, status.Error(codes.Unimplemented, "method Stop not implemented") } func (UnimplementedComputationRunnerServer) mustEmbedUnimplementedComputationRunnerServer() {} func (UnimplementedComputationRunnerServer) testEmbeddedByValue() {} @@ -96,7 +96,7 @@ type UnsafeComputationRunnerServer interface { } func RegisterComputationRunnerServer(s grpc.ServiceRegistrar, srv ComputationRunnerServer) { - // If the following call pancis, it indicates UnimplementedComputationRunnerServer was + // If the following call panics, it indicates UnimplementedComputationRunnerServer was // embedded by pointer and is nil. This will cause panics if an // unimplemented method is ever invoked, so we test this at initialization // time to prevent it from happening at runtime later due to I/O. diff --git a/cmd/attestation-service/main.go b/cmd/attestation-service/main.go index 5c9ff527..7aaeaf8f 100644 --- a/cmd/attestation-service/main.go +++ b/cmd/attestation-service/main.go @@ -17,6 +17,7 @@ import ( attestationpb "github.com/ultravioletrs/cocos/internal/proto/attestation/v1" "github.com/ultravioletrs/cocos/pkg/attestation" "github.com/ultravioletrs/cocos/pkg/attestation/azure" + "github.com/ultravioletrs/cocos/pkg/attestation/ccaa" "github.com/ultravioletrs/cocos/pkg/attestation/eat" "github.com/ultravioletrs/cocos/pkg/attestation/tdx" "github.com/ultravioletrs/cocos/pkg/attestation/vtpm" @@ -30,14 +31,27 @@ const ( ) type config struct { - LogLevel string `env:"ATTESTATION_LOG_LEVEL" envDefault:"debug"` - Vmpl int `env:"ATTESTATION_VMPL" envDefault:"2"` - AgentMaaURL string `env:"AGENT_MAA_URL" envDefault:"https://sharedeus2.eus2.attest.azure.net"` - AgentOSBuild string `env:"AGENT_OS_BUILD" envDefault:"UVC"` - AgentOSDistro string `env:"AGENT_OS_DISTRO" envDefault:"UVC"` - AgentOSType string `env:"AGENT_OS_TYPE" envDefault:"UVC"` - EATFormat string `env:"ATTESTATION_EAT_FORMAT" envDefault:"CBOR"` // JWT or CBOR - EATIssuer string `env:"ATTESTATION_EAT_ISSUER" envDefault:"cocos-attestation-service"` + LogLevel string `env:"ATTESTATION_LOG_LEVEL" envDefault:"debug"` + Vmpl int `env:"ATTESTATION_VMPL" envDefault:"2"` + AgentMaaURL string `env:"AGENT_MAA_URL" envDefault:"https://sharedeus2.eus2.attest.azure.net"` + AgentOSBuild string `env:"AGENT_OS_BUILD" envDefault:"UVC"` + AgentOSDistro string `env:"AGENT_OS_DISTRO" envDefault:"UVC"` + AgentOSType string `env:"AGENT_OS_TYPE" envDefault:"UVC"` + EATFormat string `env:"ATTESTATION_EAT_FORMAT" envDefault:"CBOR"` // JWT or CBOR + EATIssuer string `env:"ATTESTATION_EAT_ISSUER" envDefault:"cocos-attestation-service"` + UseCCAttestationAgent bool `env:"USE_CC_ATTESTATION_AGENT" envDefault:"false"` + CCAgentAddress string `env:"CC_AGENT_ADDRESS" envDefault:"127.0.0.1:50002"` + + // Future KBS Integration Configuration + // When KBS support is added, these fields will enable: + // - Remote attestation verification via KBS + // - Encrypted algorithm/dataset retrieval + // - Per-computation secret provisioning + // + // Example future fields: + // KBSEndpoint string `env:"KBS_ENDPOINT" envDefault:""` // Optional KBS URL + // KBSEnabled bool `env:"KBS_ENABLED" envDefault:"false"` + // KBSTimeout int `env:"KBS_TIMEOUT_SECONDS" envDefault:"30"` } func main() { @@ -73,18 +87,34 @@ func main() { ) azure.InitializeDefaultMAAVars(azureConfig) - switch ccPlatform { - case attestation.SNP: - provider = vtpm.NewProvider(false, uint(cfg.Vmpl)) - case attestation.SNPvTPM: - provider = vtpm.NewProvider(true, uint(cfg.Vmpl)) - case attestation.Azure: - provider = azure.NewProvider() - case attestation.TDX: - provider = tdx.NewProvider() - case attestation.NoCC: - logger.Info("TEE device not found") - provider = &attestation.EmptyProvider{} + // Try to use CC attestation-agent if configured + if cfg.UseCCAttestationAgent { + logger.Info(fmt.Sprintf("attempting to use CC attestation-agent at %s", cfg.CCAgentAddress)) + ccProvider, err := ccaa.NewProvider(cfg.CCAgentAddress) + if err != nil { + logger.Warn(fmt.Sprintf("failed to connect to CC attestation-agent: %s, falling back to direct providers", err)) + } else { + logger.Info("successfully connected to CC attestation-agent") + provider = ccProvider + defer ccProvider.Close() + } + } + + // Fallback to direct providers if CC AA not configured or unavailable + if provider == nil { + switch ccPlatform { + case attestation.SNP: + provider = vtpm.NewProvider(false, uint(cfg.Vmpl)) + case attestation.SNPvTPM: + provider = vtpm.NewProvider(true, uint(cfg.Vmpl)) + case attestation.Azure: + provider = azure.NewProvider() + case attestation.TDX: + provider = tdx.NewProvider() + case attestation.NoCC: + logger.Info("TEE device not found") + provider = &attestation.EmptyProvider{} + } } if ccPlatform == attestation.SNP || ccPlatform == attestation.SNPvTPM { diff --git a/hal/linux/Config.in b/hal/linux/Config.in index 48534b95..feb4a813 100644 --- a/hal/linux/Config.in +++ b/hal/linux/Config.in @@ -1,5 +1,7 @@ source "$BR2_EXTERNAL_COCOS_PATH/package/agent/Config.in" source "$BR2_EXTERNAL_COCOS_PATH/package/attestation-service/Config.in" +source "$BR2_EXTERNAL_COCOS_PATH/package/cc-attestation-agent/Config.in" +source "$BR2_EXTERNAL_COCOS_PATH/package/cc-attestation-adapter/Config.in" source "$BR2_EXTERNAL_COCOS_PATH/package/wasmedge/Config.in" source "$BR2_EXTERNAL_COCOS_PATH/package/log-forwarder/Config.in" source "$BR2_EXTERNAL_COCOS_PATH/package/computation-runner/Config.in" diff --git a/hal/linux/configs/cocos_defconfig b/hal/linux/configs/cocos_defconfig index 0162c941..6aa1244c 100644 --- a/hal/linux/configs/cocos_defconfig +++ b/hal/linux/configs/cocos_defconfig @@ -71,3 +71,7 @@ BR2_TOOLCHAIN_BUILDROOT_LIBSTDCPP=y BR2_PACKAGE_GCC=y BR2_PACKAGE_GCC_TARGET=y BR2_PACKAGE_LIBSTDCPP=y + +# Attestation Backend +BR2_PACKAGE_ATTESTATION_BACKEND_COCOS=y +# BR2_PACKAGE_ATTESTATION_BACKEND_CC is not set diff --git a/hal/linux/package/attestation-service/Config.in b/hal/linux/package/attestation-service/Config.in index 7afac554..051dc3a0 100644 --- a/hal/linux/package/attestation-service/Config.in +++ b/hal/linux/package/attestation-service/Config.in @@ -1,6 +1,42 @@ -config BR2_PACKAGE_ATTESTATION_SERVICE - bool "attestation-service" +choice + prompt "Attestation Backend" + default BR2_PACKAGE_ATTESTATION_BACKEND_COCOS help - Attestation Service for confidential computing attestation. + Select the attestation backend to use for confidential computing. + + The Cocos AI attestation service is the native implementation + that generates EAT (Entity Attestation Token) tokens locally. + + The Confidential Containers attestation-agent is an alternative + implementation that supports the KBS (Key Broker Service) protocol + for optional remote attestation and secret provisioning. +config BR2_PACKAGE_ATTESTATION_BACKEND_COCOS + bool "Cocos AI Attestation Service" + help + Native Cocos AI attestation service that generates EAT tokens + locally for TEE attestation (SNP, TDX, vTPM, Azure). + + This is the default and recommended option for most use cases. + https://github.com/ultravioletrs/cocos + +config BR2_PACKAGE_ATTESTATION_BACKEND_CC + bool "Confidential Containers Attestation Agent" + depends on BR2_PACKAGE_HOST_RUSTC + help + Confidential Containers attestation-agent with optional KBS + protocol support for remote attestation and secret provisioning. + + Can operate in local mode (without KBS) or with KBS endpoint + configured per-computation for encrypted data retrieval. + + Requires Rust toolchain for building. + + https://github.com/confidential-containers/guest-components + +endchoice + +config BR2_PACKAGE_ATTESTATION_SERVICE + bool + default y if BR2_PACKAGE_ATTESTATION_BACKEND_COCOS diff --git a/hal/linux/package/cc-attestation-agent/Config.in b/hal/linux/package/cc-attestation-agent/Config.in new file mode 100644 index 00000000..0229ff73 --- /dev/null +++ b/hal/linux/package/cc-attestation-agent/Config.in @@ -0,0 +1,31 @@ +config BR2_PACKAGE_CC_ATTESTATION_AGENT + bool + default y if BR2_PACKAGE_ATTESTATION_BACKEND_CC + depends on BR2_PACKAGE_HOST_RUSTC + select BR2_PACKAGE_PROTOBUF + select BR2_PACKAGE_OPENSSL + help + Confidential Containers attestation-agent for TEE attestation + with optional KBS (Key Broker Service) protocol support. + + This package provides an alternative attestation backend that + can operate in local mode or connect to a KBS for remote + attestation and encrypted secret provisioning. + + https://github.com/confidential-containers/guest-components + +if BR2_PACKAGE_CC_ATTESTATION_AGENT + +config BR2_PACKAGE_CC_ATTESTATION_AGENT_KBS_URL + string "Default KBS URL (optional)" + default "" + help + Optional default KBS (Key Broker Service) URL for remote + attestation and secret provisioning. + + Leave empty to operate in local attestation mode only. + Can be overridden per-computation via environment variables. + + Example: https://kbs.example.com:8080 + +endif diff --git a/hal/linux/package/cc-attestation-agent/cc-attestation-agent-setup.sh b/hal/linux/package/cc-attestation-agent/cc-attestation-agent-setup.sh new file mode 100644 index 00000000..680ceb29 --- /dev/null +++ b/hal/linux/package/cc-attestation-agent/cc-attestation-agent-setup.sh @@ -0,0 +1,5 @@ +#!/bin/bash +# Setup permissions for attestation socket directory + +mkdir -p /run/cocos +chmod 755 /run/cocos diff --git a/hal/linux/package/cc-attestation-agent/cc-attestation-agent.mk b/hal/linux/package/cc-attestation-agent/cc-attestation-agent.mk new file mode 100644 index 00000000..95447aba --- /dev/null +++ b/hal/linux/package/cc-attestation-agent/cc-attestation-agent.mk @@ -0,0 +1,37 @@ +################################################################################ +# +# cc-attestation-agent +# +################################################################################ + +CC_ATTESTATION_AGENT_VERSION = v0.16.0 +CC_ATTESTATION_AGENT_SITE = $(call github,confidential-containers,guest-components,$(CC_ATTESTATION_AGENT_VERSION)) +CC_ATTESTATION_AGENT_LICENSE = Apache-2.0 +CC_ATTESTATION_AGENT_LICENSE_FILES = LICENSE + +CC_ATTESTATION_AGENT_DEPENDENCIES = host-rustc openssl protobuf + +# Build the attestation-agent from the guest-components repository with gRPC support +define CC_ATTESTATION_AGENT_BUILD_CMDS + cd $(@D)/attestation-agent && \ + $(TARGET_MAKE_ENV) \ + CARGO_HOME=$(@D)/.cargo \ + make ATTESTER=all-attesters ttrpc=false +endef + +define CC_ATTESTATION_AGENT_INSTALL_TARGET_CMDS + $(INSTALL) -D -m 0755 \ + $(@D)/target/$(RUSTC_TARGET_NAME)/release/attestation-agent \ + $(TARGET_DIR)/usr/bin/attestation-agent +endef + +define CC_ATTESTATION_AGENT_INSTALL_INIT_SYSTEMD + $(INSTALL) -D -m 0644 \ + $(BR2_EXTERNAL_COCOS_PATH)/package/cc-attestation-agent/cc-attestation-agent.service \ + $(TARGET_DIR)/usr/lib/systemd/system/attestation-agent.service + $(INSTALL) -D -m 0750 \ + $(BR2_EXTERNAL_COCOS_PATH)/package/cc-attestation-agent/cc-attestation-agent-setup.sh \ + $(TARGET_DIR)/cocos_init/attestation_setup.sh +endef + +$(eval $(generic-package)) diff --git a/hal/linux/package/cc-attestation-agent/cc-attestation-agent.service b/hal/linux/package/cc-attestation-agent/cc-attestation-agent.service new file mode 100644 index 00000000..d3aed913 --- /dev/null +++ b/hal/linux/package/cc-attestation-agent/cc-attestation-agent.service @@ -0,0 +1,13 @@ +[Unit] +Description=Confidential Containers Attestation Agent (gRPC) +After=network.target + +[Service] +Type=simple +ExecStart=/usr/bin/attestation-agent --attestation_sock 127.0.0.1:50002 +Restart=always +RestartSec=5 +Environment=RUST_LOG=info + +[Install] +WantedBy=multi-user.target diff --git a/init/systemd/attestation-service.service b/init/systemd/attestation-service.service index 43ff86dd..7c6353ee 100644 --- a/init/systemd/attestation-service.service +++ b/init/systemd/attestation-service.service @@ -1,6 +1,7 @@ [Unit] Description=Cocos Attestation Service After=network.target +Wants=attestation-agent.service [Service] Type=simple @@ -10,6 +11,10 @@ RestartSec=5 Environment=ATTESTATION_LOG_LEVEL=debug Environment=ATTESTATION_SERVICE_SOCKET=/run/cocos/attestation.sock Environment=ATTESTATION_VMPL=2 +Environment=ATTESTATION_EAT_FORMAT=CBOR +# Enable CC Attestation-Agent backend +Environment=USE_CC_ATTESTATION_AGENT=true +Environment=CC_AGENT_ADDRESS=127.0.0.1:50002 ExecStartPre=/cocos_init/attestation_setup.sh [Install] diff --git a/internal/proto/attestation-agent/attestation-agent.pb.go b/internal/proto/attestation-agent/attestation-agent.pb.go new file mode 100644 index 00000000..13f73b81 --- /dev/null +++ b/internal/proto/attestation-agent/attestation-agent.pb.go @@ -0,0 +1,687 @@ +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.36.11 +// protoc v6.33.1 +// source: internal/proto/attestation-agent/attestation-agent.proto + +package attestation_agent + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" + unsafe "unsafe" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type RuntimeMeasurementResult int32 + +const ( + RuntimeMeasurementResult_OK RuntimeMeasurementResult = 0 + RuntimeMeasurementResult_NOT_SUPPORTED RuntimeMeasurementResult = 1 + RuntimeMeasurementResult_NOT_ENABLED RuntimeMeasurementResult = 2 +) + +// Enum value maps for RuntimeMeasurementResult. +var ( + RuntimeMeasurementResult_name = map[int32]string{ + 0: "OK", + 1: "NOT_SUPPORTED", + 2: "NOT_ENABLED", + } + RuntimeMeasurementResult_value = map[string]int32{ + "OK": 0, + "NOT_SUPPORTED": 1, + "NOT_ENABLED": 2, + } +) + +func (x RuntimeMeasurementResult) Enum() *RuntimeMeasurementResult { + p := new(RuntimeMeasurementResult) + *p = x + return p +} + +func (x RuntimeMeasurementResult) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (RuntimeMeasurementResult) Descriptor() protoreflect.EnumDescriptor { + return file_internal_proto_attestation_agent_attestation_agent_proto_enumTypes[0].Descriptor() +} + +func (RuntimeMeasurementResult) Type() protoreflect.EnumType { + return &file_internal_proto_attestation_agent_attestation_agent_proto_enumTypes[0] +} + +func (x RuntimeMeasurementResult) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use RuntimeMeasurementResult.Descriptor instead. +func (RuntimeMeasurementResult) EnumDescriptor() ([]byte, []int) { + return file_internal_proto_attestation_agent_attestation_agent_proto_rawDescGZIP(), []int{0} +} + +// Get the primary evidence from the guest. +type GetEvidenceRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + RuntimeData []byte `protobuf:"bytes,1,opt,name=RuntimeData,proto3" json:"RuntimeData,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetEvidenceRequest) Reset() { + *x = GetEvidenceRequest{} + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetEvidenceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetEvidenceRequest) ProtoMessage() {} + +func (x *GetEvidenceRequest) ProtoReflect() protoreflect.Message { + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetEvidenceRequest.ProtoReflect.Descriptor instead. +func (*GetEvidenceRequest) Descriptor() ([]byte, []int) { + return file_internal_proto_attestation_agent_attestation_agent_proto_rawDescGZIP(), []int{0} +} + +func (x *GetEvidenceRequest) GetRuntimeData() []byte { + if x != nil { + return x.RuntimeData + } + return nil +} + +type GetAdditionalEvidenceRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + RuntimeData []byte `protobuf:"bytes,1,opt,name=RuntimeData,proto3" json:"RuntimeData,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetAdditionalEvidenceRequest) Reset() { + *x = GetAdditionalEvidenceRequest{} + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetAdditionalEvidenceRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetAdditionalEvidenceRequest) ProtoMessage() {} + +func (x *GetAdditionalEvidenceRequest) ProtoReflect() protoreflect.Message { + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetAdditionalEvidenceRequest.ProtoReflect.Descriptor instead. +func (*GetAdditionalEvidenceRequest) Descriptor() ([]byte, []int) { + return file_internal_proto_attestation_agent_attestation_agent_proto_rawDescGZIP(), []int{1} +} + +func (x *GetAdditionalEvidenceRequest) GetRuntimeData() []byte { + if x != nil { + return x.RuntimeData + } + return nil +} + +type GetEvidenceResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Evidence []byte `protobuf:"bytes,1,opt,name=Evidence,proto3" json:"Evidence,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetEvidenceResponse) Reset() { + *x = GetEvidenceResponse{} + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetEvidenceResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetEvidenceResponse) ProtoMessage() {} + +func (x *GetEvidenceResponse) ProtoReflect() protoreflect.Message { + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[2] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetEvidenceResponse.ProtoReflect.Descriptor instead. +func (*GetEvidenceResponse) Descriptor() ([]byte, []int) { + return file_internal_proto_attestation_agent_attestation_agent_proto_rawDescGZIP(), []int{2} +} + +func (x *GetEvidenceResponse) GetEvidence() []byte { + if x != nil { + return x.Evidence + } + return nil +} + +type GetTokenRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + TokenType string `protobuf:"bytes,1,opt,name=TokenType,proto3" json:"TokenType,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetTokenRequest) Reset() { + *x = GetTokenRequest{} + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetTokenRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTokenRequest) ProtoMessage() {} + +func (x *GetTokenRequest) ProtoReflect() protoreflect.Message { + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[3] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTokenRequest.ProtoReflect.Descriptor instead. +func (*GetTokenRequest) Descriptor() ([]byte, []int) { + return file_internal_proto_attestation_agent_attestation_agent_proto_rawDescGZIP(), []int{3} +} + +func (x *GetTokenRequest) GetTokenType() string { + if x != nil { + return x.TokenType + } + return "" +} + +type GetTokenResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Token []byte `protobuf:"bytes,1,opt,name=Token,proto3" json:"Token,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetTokenResponse) Reset() { + *x = GetTokenResponse{} + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetTokenResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTokenResponse) ProtoMessage() {} + +func (x *GetTokenResponse) ProtoReflect() protoreflect.Message { + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[4] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTokenResponse.ProtoReflect.Descriptor instead. +func (*GetTokenResponse) Descriptor() ([]byte, []int) { + return file_internal_proto_attestation_agent_attestation_agent_proto_rawDescGZIP(), []int{4} +} + +func (x *GetTokenResponse) GetToken() []byte { + if x != nil { + return x.Token + } + return nil +} + +// Extend the dynamic/runtime measurement with given materials. This would change the state +// of current TEE's status, e.g. TDX's RTMR, (v)TPM's PCR, by adding a record in eventlog. +type ExtendRuntimeMeasurementRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + // The domain to which this event entry belongs. This domain is used to distinguish the semantics of log entries in different contexts. + Domain string `protobuf:"bytes,1,opt,name=Domain,proto3" json:"Domain,omitempty"` + // Concrete operation type that this event entry records. + Operation string `protobuf:"bytes,2,opt,name=Operation,proto3" json:"Operation,omitempty"` + // Detailed content of the operation that this event entry records. + Content string `protobuf:"bytes,3,opt,name=Content,proto3" json:"Content,omitempty"` + // Which PCR will be extended with the hash of this entry. + RegisterIndex *uint64 `protobuf:"varint,4,opt,name=RegisterIndex,proto3,oneof" json:"RegisterIndex,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExtendRuntimeMeasurementRequest) Reset() { + *x = ExtendRuntimeMeasurementRequest{} + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExtendRuntimeMeasurementRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtendRuntimeMeasurementRequest) ProtoMessage() {} + +func (x *ExtendRuntimeMeasurementRequest) ProtoReflect() protoreflect.Message { + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[5] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExtendRuntimeMeasurementRequest.ProtoReflect.Descriptor instead. +func (*ExtendRuntimeMeasurementRequest) Descriptor() ([]byte, []int) { + return file_internal_proto_attestation_agent_attestation_agent_proto_rawDescGZIP(), []int{5} +} + +func (x *ExtendRuntimeMeasurementRequest) GetDomain() string { + if x != nil { + return x.Domain + } + return "" +} + +func (x *ExtendRuntimeMeasurementRequest) GetOperation() string { + if x != nil { + return x.Operation + } + return "" +} + +func (x *ExtendRuntimeMeasurementRequest) GetContent() string { + if x != nil { + return x.Content + } + return "" +} + +func (x *ExtendRuntimeMeasurementRequest) GetRegisterIndex() uint64 { + if x != nil && x.RegisterIndex != nil { + return *x.RegisterIndex + } + return 0 +} + +type ExtendRuntimeMeasurementResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Result RuntimeMeasurementResult `protobuf:"varint,1,opt,name=Result,proto3,enum=attestation_agent.RuntimeMeasurementResult" json:"Result,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ExtendRuntimeMeasurementResponse) Reset() { + *x = ExtendRuntimeMeasurementResponse{} + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ExtendRuntimeMeasurementResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtendRuntimeMeasurementResponse) ProtoMessage() {} + +func (x *ExtendRuntimeMeasurementResponse) ProtoReflect() protoreflect.Message { + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[6] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExtendRuntimeMeasurementResponse.ProtoReflect.Descriptor instead. +func (*ExtendRuntimeMeasurementResponse) Descriptor() ([]byte, []int) { + return file_internal_proto_attestation_agent_attestation_agent_proto_rawDescGZIP(), []int{6} +} + +func (x *ExtendRuntimeMeasurementResponse) GetResult() RuntimeMeasurementResult { + if x != nil { + return x.Result + } + return RuntimeMeasurementResult_OK +} + +type BindInitDataRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Digest []byte `protobuf:"bytes,1,opt,name=Digest,proto3" json:"Digest,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BindInitDataRequest) Reset() { + *x = BindInitDataRequest{} + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[7] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BindInitDataRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BindInitDataRequest) ProtoMessage() {} + +func (x *BindInitDataRequest) ProtoReflect() protoreflect.Message { + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[7] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BindInitDataRequest.ProtoReflect.Descriptor instead. +func (*BindInitDataRequest) Descriptor() ([]byte, []int) { + return file_internal_proto_attestation_agent_attestation_agent_proto_rawDescGZIP(), []int{7} +} + +func (x *BindInitDataRequest) GetDigest() []byte { + if x != nil { + return x.Digest + } + return nil +} + +type BindInitDataResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *BindInitDataResponse) Reset() { + *x = BindInitDataResponse{} + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[8] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *BindInitDataResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*BindInitDataResponse) ProtoMessage() {} + +func (x *BindInitDataResponse) ProtoReflect() protoreflect.Message { + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[8] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use BindInitDataResponse.ProtoReflect.Descriptor instead. +func (*BindInitDataResponse) Descriptor() ([]byte, []int) { + return file_internal_proto_attestation_agent_attestation_agent_proto_rawDescGZIP(), []int{8} +} + +type GetTeeTypeRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetTeeTypeRequest) Reset() { + *x = GetTeeTypeRequest{} + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[9] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetTeeTypeRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTeeTypeRequest) ProtoMessage() {} + +func (x *GetTeeTypeRequest) ProtoReflect() protoreflect.Message { + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[9] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTeeTypeRequest.ProtoReflect.Descriptor instead. +func (*GetTeeTypeRequest) Descriptor() ([]byte, []int) { + return file_internal_proto_attestation_agent_attestation_agent_proto_rawDescGZIP(), []int{9} +} + +type GetTeeTypeResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Tee string `protobuf:"bytes,1,opt,name=tee,proto3" json:"tee,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetTeeTypeResponse) Reset() { + *x = GetTeeTypeResponse{} + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[10] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetTeeTypeResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetTeeTypeResponse) ProtoMessage() {} + +func (x *GetTeeTypeResponse) ProtoReflect() protoreflect.Message { + mi := &file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[10] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetTeeTypeResponse.ProtoReflect.Descriptor instead. +func (*GetTeeTypeResponse) Descriptor() ([]byte, []int) { + return file_internal_proto_attestation_agent_attestation_agent_proto_rawDescGZIP(), []int{10} +} + +func (x *GetTeeTypeResponse) GetTee() string { + if x != nil { + return x.Tee + } + return "" +} + +var File_internal_proto_attestation_agent_attestation_agent_proto protoreflect.FileDescriptor + +const file_internal_proto_attestation_agent_attestation_agent_proto_rawDesc = "" + + "\n" + + "8internal/proto/attestation-agent/attestation-agent.proto\x12\x11attestation_agent\"6\n" + + "\x12GetEvidenceRequest\x12 \n" + + "\vRuntimeData\x18\x01 \x01(\fR\vRuntimeData\"@\n" + + "\x1cGetAdditionalEvidenceRequest\x12 \n" + + "\vRuntimeData\x18\x01 \x01(\fR\vRuntimeData\"1\n" + + "\x13GetEvidenceResponse\x12\x1a\n" + + "\bEvidence\x18\x01 \x01(\fR\bEvidence\"/\n" + + "\x0fGetTokenRequest\x12\x1c\n" + + "\tTokenType\x18\x01 \x01(\tR\tTokenType\"(\n" + + "\x10GetTokenResponse\x12\x14\n" + + "\x05Token\x18\x01 \x01(\fR\x05Token\"\xae\x01\n" + + "\x1fExtendRuntimeMeasurementRequest\x12\x16\n" + + "\x06Domain\x18\x01 \x01(\tR\x06Domain\x12\x1c\n" + + "\tOperation\x18\x02 \x01(\tR\tOperation\x12\x18\n" + + "\aContent\x18\x03 \x01(\tR\aContent\x12)\n" + + "\rRegisterIndex\x18\x04 \x01(\x04H\x00R\rRegisterIndex\x88\x01\x01B\x10\n" + + "\x0e_RegisterIndex\"g\n" + + " ExtendRuntimeMeasurementResponse\x12C\n" + + "\x06Result\x18\x01 \x01(\x0e2+.attestation_agent.RuntimeMeasurementResultR\x06Result\"-\n" + + "\x13BindInitDataRequest\x12\x16\n" + + "\x06Digest\x18\x01 \x01(\fR\x06Digest\"\x16\n" + + "\x14BindInitDataResponse\"\x13\n" + + "\x11GetTeeTypeRequest\"&\n" + + "\x12GetTeeTypeResponse\x12\x10\n" + + "\x03tee\x18\x01 \x01(\tR\x03tee*F\n" + + "\x18RuntimeMeasurementResult\x12\x06\n" + + "\x02OK\x10\x00\x12\x11\n" + + "\rNOT_SUPPORTED\x10\x01\x12\x0f\n" + + "\vNOT_ENABLED\x10\x022\x8c\x05\n" + + "\x17AttestationAgentService\x12^\n" + + "\vGetEvidence\x12%.attestation_agent.GetEvidenceRequest\x1a&.attestation_agent.GetEvidenceResponse\"\x00\x12r\n" + + "\x15GetAdditionalEvidence\x12/.attestation_agent.GetAdditionalEvidenceRequest\x1a&.attestation_agent.GetEvidenceResponse\"\x00\x12U\n" + + "\bGetToken\x12\".attestation_agent.GetTokenRequest\x1a#.attestation_agent.GetTokenResponse\"\x00\x12\x85\x01\n" + + "\x18ExtendRuntimeMeasurement\x122.attestation_agent.ExtendRuntimeMeasurementRequest\x1a3.attestation_agent.ExtendRuntimeMeasurementResponse\"\x00\x12a\n" + + "\fBindInitData\x12&.attestation_agent.BindInitDataRequest\x1a'.attestation_agent.BindInitDataResponse\"\x00\x12[\n" + + "\n" + + "GetTeeType\x12$.attestation_agent.GetTeeTypeRequest\x1a%.attestation_agent.GetTeeTypeResponse\"\x00BSZQgithub.com/ultravioletrs/cocos/internal/proto/attestation-agent;attestation_agentb\x06proto3" + +var ( + file_internal_proto_attestation_agent_attestation_agent_proto_rawDescOnce sync.Once + file_internal_proto_attestation_agent_attestation_agent_proto_rawDescData []byte +) + +func file_internal_proto_attestation_agent_attestation_agent_proto_rawDescGZIP() []byte { + file_internal_proto_attestation_agent_attestation_agent_proto_rawDescOnce.Do(func() { + file_internal_proto_attestation_agent_attestation_agent_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_internal_proto_attestation_agent_attestation_agent_proto_rawDesc), len(file_internal_proto_attestation_agent_attestation_agent_proto_rawDesc))) + }) + return file_internal_proto_attestation_agent_attestation_agent_proto_rawDescData +} + +var file_internal_proto_attestation_agent_attestation_agent_proto_enumTypes = make([]protoimpl.EnumInfo, 1) +var file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 11) +var file_internal_proto_attestation_agent_attestation_agent_proto_goTypes = []any{ + (RuntimeMeasurementResult)(0), // 0: attestation_agent.RuntimeMeasurementResult + (*GetEvidenceRequest)(nil), // 1: attestation_agent.GetEvidenceRequest + (*GetAdditionalEvidenceRequest)(nil), // 2: attestation_agent.GetAdditionalEvidenceRequest + (*GetEvidenceResponse)(nil), // 3: attestation_agent.GetEvidenceResponse + (*GetTokenRequest)(nil), // 4: attestation_agent.GetTokenRequest + (*GetTokenResponse)(nil), // 5: attestation_agent.GetTokenResponse + (*ExtendRuntimeMeasurementRequest)(nil), // 6: attestation_agent.ExtendRuntimeMeasurementRequest + (*ExtendRuntimeMeasurementResponse)(nil), // 7: attestation_agent.ExtendRuntimeMeasurementResponse + (*BindInitDataRequest)(nil), // 8: attestation_agent.BindInitDataRequest + (*BindInitDataResponse)(nil), // 9: attestation_agent.BindInitDataResponse + (*GetTeeTypeRequest)(nil), // 10: attestation_agent.GetTeeTypeRequest + (*GetTeeTypeResponse)(nil), // 11: attestation_agent.GetTeeTypeResponse +} +var file_internal_proto_attestation_agent_attestation_agent_proto_depIdxs = []int32{ + 0, // 0: attestation_agent.ExtendRuntimeMeasurementResponse.Result:type_name -> attestation_agent.RuntimeMeasurementResult + 1, // 1: attestation_agent.AttestationAgentService.GetEvidence:input_type -> attestation_agent.GetEvidenceRequest + 2, // 2: attestation_agent.AttestationAgentService.GetAdditionalEvidence:input_type -> attestation_agent.GetAdditionalEvidenceRequest + 4, // 3: attestation_agent.AttestationAgentService.GetToken:input_type -> attestation_agent.GetTokenRequest + 6, // 4: attestation_agent.AttestationAgentService.ExtendRuntimeMeasurement:input_type -> attestation_agent.ExtendRuntimeMeasurementRequest + 8, // 5: attestation_agent.AttestationAgentService.BindInitData:input_type -> attestation_agent.BindInitDataRequest + 10, // 6: attestation_agent.AttestationAgentService.GetTeeType:input_type -> attestation_agent.GetTeeTypeRequest + 3, // 7: attestation_agent.AttestationAgentService.GetEvidence:output_type -> attestation_agent.GetEvidenceResponse + 3, // 8: attestation_agent.AttestationAgentService.GetAdditionalEvidence:output_type -> attestation_agent.GetEvidenceResponse + 5, // 9: attestation_agent.AttestationAgentService.GetToken:output_type -> attestation_agent.GetTokenResponse + 7, // 10: attestation_agent.AttestationAgentService.ExtendRuntimeMeasurement:output_type -> attestation_agent.ExtendRuntimeMeasurementResponse + 9, // 11: attestation_agent.AttestationAgentService.BindInitData:output_type -> attestation_agent.BindInitDataResponse + 11, // 12: attestation_agent.AttestationAgentService.GetTeeType:output_type -> attestation_agent.GetTeeTypeResponse + 7, // [7:13] is the sub-list for method output_type + 1, // [1:7] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_internal_proto_attestation_agent_attestation_agent_proto_init() } +func file_internal_proto_attestation_agent_attestation_agent_proto_init() { + if File_internal_proto_attestation_agent_attestation_agent_proto != nil { + return + } + file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes[5].OneofWrappers = []any{} + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: unsafe.Slice(unsafe.StringData(file_internal_proto_attestation_agent_attestation_agent_proto_rawDesc), len(file_internal_proto_attestation_agent_attestation_agent_proto_rawDesc)), + NumEnums: 1, + NumMessages: 11, + NumExtensions: 0, + NumServices: 1, + }, + GoTypes: file_internal_proto_attestation_agent_attestation_agent_proto_goTypes, + DependencyIndexes: file_internal_proto_attestation_agent_attestation_agent_proto_depIdxs, + EnumInfos: file_internal_proto_attestation_agent_attestation_agent_proto_enumTypes, + MessageInfos: file_internal_proto_attestation_agent_attestation_agent_proto_msgTypes, + }.Build() + File_internal_proto_attestation_agent_attestation_agent_proto = out.File + file_internal_proto_attestation_agent_attestation_agent_proto_goTypes = nil + file_internal_proto_attestation_agent_attestation_agent_proto_depIdxs = nil +} diff --git a/internal/proto/attestation-agent/attestation-agent.proto b/internal/proto/attestation-agent/attestation-agent.proto new file mode 100644 index 00000000..2ac430a0 --- /dev/null +++ b/internal/proto/attestation-agent/attestation-agent.proto @@ -0,0 +1,73 @@ +syntax = "proto3"; + +package attestation_agent; + +option go_package = "github.com/ultravioletrs/cocos/internal/proto/attestation-agent;attestation_agent"; + +// Get the primary evidence from the guest. +message GetEvidenceRequest { + bytes RuntimeData = 1; +} + +message GetAdditionalEvidenceRequest { + bytes RuntimeData = 1; +} + +message GetEvidenceResponse { + bytes Evidence = 1; +} + +message GetTokenRequest { + string TokenType = 1; +} + +message GetTokenResponse { + bytes Token = 1; +} + +// Extend the dynamic/runtime measurement with given materials. This would change the state +// of current TEE's status, e.g. TDX's RTMR, (v)TPM's PCR, by adding a record in eventlog. +message ExtendRuntimeMeasurementRequest { + // The domain to which this event entry belongs. This domain is used to distinguish the semantics of log entries in different contexts. + string Domain = 1; + + // Concrete operation type that this event entry records. + string Operation = 2; + + // Detailed content of the operation that this event entry records. + string Content = 3; + + // Which PCR will be extended with the hash of this entry. + optional uint64 RegisterIndex = 4; +} + +enum RuntimeMeasurementResult { + OK = 0; + NOT_SUPPORTED = 1; + NOT_ENABLED = 2; +} + +message ExtendRuntimeMeasurementResponse { + RuntimeMeasurementResult Result = 1; +} + +message BindInitDataRequest { + bytes Digest = 1; +} + +message BindInitDataResponse {} + +message GetTeeTypeRequest {} + +message GetTeeTypeResponse { + string tee = 1; +} + +service AttestationAgentService { + rpc GetEvidence(GetEvidenceRequest) returns (GetEvidenceResponse) {}; + rpc GetAdditionalEvidence(GetAdditionalEvidenceRequest) returns (GetEvidenceResponse) {}; + rpc GetToken(GetTokenRequest) returns (GetTokenResponse) {}; + rpc ExtendRuntimeMeasurement(ExtendRuntimeMeasurementRequest) returns (ExtendRuntimeMeasurementResponse) {}; + rpc BindInitData(BindInitDataRequest) returns (BindInitDataResponse) {}; + rpc GetTeeType(GetTeeTypeRequest) returns (GetTeeTypeResponse) {}; +} diff --git a/internal/proto/attestation-agent/attestation-agent_grpc.pb.go b/internal/proto/attestation-agent/attestation-agent_grpc.pb.go new file mode 100644 index 00000000..e2b5b3ea --- /dev/null +++ b/internal/proto/attestation-agent/attestation-agent_grpc.pb.go @@ -0,0 +1,312 @@ +// Code generated by protoc-gen-go-grpc. DO NOT EDIT. +// versions: +// - protoc-gen-go-grpc v1.6.0 +// - protoc v6.33.1 +// source: internal/proto/attestation-agent/attestation-agent.proto + +package attestation_agent + +import ( + context "context" + grpc "google.golang.org/grpc" + codes "google.golang.org/grpc/codes" + status "google.golang.org/grpc/status" +) + +// This is a compile-time assertion to ensure that this generated file +// is compatible with the grpc package it is being compiled against. +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 + +const ( + AttestationAgentService_GetEvidence_FullMethodName = "/attestation_agent.AttestationAgentService/GetEvidence" + AttestationAgentService_GetAdditionalEvidence_FullMethodName = "/attestation_agent.AttestationAgentService/GetAdditionalEvidence" + AttestationAgentService_GetToken_FullMethodName = "/attestation_agent.AttestationAgentService/GetToken" + AttestationAgentService_ExtendRuntimeMeasurement_FullMethodName = "/attestation_agent.AttestationAgentService/ExtendRuntimeMeasurement" + AttestationAgentService_BindInitData_FullMethodName = "/attestation_agent.AttestationAgentService/BindInitData" + AttestationAgentService_GetTeeType_FullMethodName = "/attestation_agent.AttestationAgentService/GetTeeType" +) + +// AttestationAgentServiceClient is the client API for AttestationAgentService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. +type AttestationAgentServiceClient interface { + GetEvidence(ctx context.Context, in *GetEvidenceRequest, opts ...grpc.CallOption) (*GetEvidenceResponse, error) + GetAdditionalEvidence(ctx context.Context, in *GetAdditionalEvidenceRequest, opts ...grpc.CallOption) (*GetEvidenceResponse, error) + GetToken(ctx context.Context, in *GetTokenRequest, opts ...grpc.CallOption) (*GetTokenResponse, error) + ExtendRuntimeMeasurement(ctx context.Context, in *ExtendRuntimeMeasurementRequest, opts ...grpc.CallOption) (*ExtendRuntimeMeasurementResponse, error) + BindInitData(ctx context.Context, in *BindInitDataRequest, opts ...grpc.CallOption) (*BindInitDataResponse, error) + GetTeeType(ctx context.Context, in *GetTeeTypeRequest, opts ...grpc.CallOption) (*GetTeeTypeResponse, error) +} + +type attestationAgentServiceClient struct { + cc grpc.ClientConnInterface +} + +func NewAttestationAgentServiceClient(cc grpc.ClientConnInterface) AttestationAgentServiceClient { + return &attestationAgentServiceClient{cc} +} + +func (c *attestationAgentServiceClient) GetEvidence(ctx context.Context, in *GetEvidenceRequest, opts ...grpc.CallOption) (*GetEvidenceResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetEvidenceResponse) + err := c.cc.Invoke(ctx, AttestationAgentService_GetEvidence_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *attestationAgentServiceClient) GetAdditionalEvidence(ctx context.Context, in *GetAdditionalEvidenceRequest, opts ...grpc.CallOption) (*GetEvidenceResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetEvidenceResponse) + err := c.cc.Invoke(ctx, AttestationAgentService_GetAdditionalEvidence_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *attestationAgentServiceClient) GetToken(ctx context.Context, in *GetTokenRequest, opts ...grpc.CallOption) (*GetTokenResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetTokenResponse) + err := c.cc.Invoke(ctx, AttestationAgentService_GetToken_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *attestationAgentServiceClient) ExtendRuntimeMeasurement(ctx context.Context, in *ExtendRuntimeMeasurementRequest, opts ...grpc.CallOption) (*ExtendRuntimeMeasurementResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(ExtendRuntimeMeasurementResponse) + err := c.cc.Invoke(ctx, AttestationAgentService_ExtendRuntimeMeasurement_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *attestationAgentServiceClient) BindInitData(ctx context.Context, in *BindInitDataRequest, opts ...grpc.CallOption) (*BindInitDataResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(BindInitDataResponse) + err := c.cc.Invoke(ctx, AttestationAgentService_BindInitData_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *attestationAgentServiceClient) GetTeeType(ctx context.Context, in *GetTeeTypeRequest, opts ...grpc.CallOption) (*GetTeeTypeResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(GetTeeTypeResponse) + err := c.cc.Invoke(ctx, AttestationAgentService_GetTeeType_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +// AttestationAgentServiceServer is the server API for AttestationAgentService service. +// All implementations must embed UnimplementedAttestationAgentServiceServer +// for forward compatibility. +type AttestationAgentServiceServer interface { + GetEvidence(context.Context, *GetEvidenceRequest) (*GetEvidenceResponse, error) + GetAdditionalEvidence(context.Context, *GetAdditionalEvidenceRequest) (*GetEvidenceResponse, error) + GetToken(context.Context, *GetTokenRequest) (*GetTokenResponse, error) + ExtendRuntimeMeasurement(context.Context, *ExtendRuntimeMeasurementRequest) (*ExtendRuntimeMeasurementResponse, error) + BindInitData(context.Context, *BindInitDataRequest) (*BindInitDataResponse, error) + GetTeeType(context.Context, *GetTeeTypeRequest) (*GetTeeTypeResponse, error) + mustEmbedUnimplementedAttestationAgentServiceServer() +} + +// UnimplementedAttestationAgentServiceServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedAttestationAgentServiceServer struct{} + +func (UnimplementedAttestationAgentServiceServer) GetEvidence(context.Context, *GetEvidenceRequest) (*GetEvidenceResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetEvidence not implemented") +} +func (UnimplementedAttestationAgentServiceServer) GetAdditionalEvidence(context.Context, *GetAdditionalEvidenceRequest) (*GetEvidenceResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetAdditionalEvidence not implemented") +} +func (UnimplementedAttestationAgentServiceServer) GetToken(context.Context, *GetTokenRequest) (*GetTokenResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetToken not implemented") +} +func (UnimplementedAttestationAgentServiceServer) ExtendRuntimeMeasurement(context.Context, *ExtendRuntimeMeasurementRequest) (*ExtendRuntimeMeasurementResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ExtendRuntimeMeasurement not implemented") +} +func (UnimplementedAttestationAgentServiceServer) BindInitData(context.Context, *BindInitDataRequest) (*BindInitDataResponse, error) { + return nil, status.Error(codes.Unimplemented, "method BindInitData not implemented") +} +func (UnimplementedAttestationAgentServiceServer) GetTeeType(context.Context, *GetTeeTypeRequest) (*GetTeeTypeResponse, error) { + return nil, status.Error(codes.Unimplemented, "method GetTeeType not implemented") +} +func (UnimplementedAttestationAgentServiceServer) mustEmbedUnimplementedAttestationAgentServiceServer() { +} +func (UnimplementedAttestationAgentServiceServer) testEmbeddedByValue() {} + +// UnsafeAttestationAgentServiceServer may be embedded to opt out of forward compatibility for this service. +// Use of this interface is not recommended, as added methods to AttestationAgentServiceServer will +// result in compilation errors. +type UnsafeAttestationAgentServiceServer interface { + mustEmbedUnimplementedAttestationAgentServiceServer() +} + +func RegisterAttestationAgentServiceServer(s grpc.ServiceRegistrar, srv AttestationAgentServiceServer) { + // If the following call panics, it indicates UnimplementedAttestationAgentServiceServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } + s.RegisterService(&AttestationAgentService_ServiceDesc, srv) +} + +func _AttestationAgentService_GetEvidence_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetEvidenceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AttestationAgentServiceServer).GetEvidence(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AttestationAgentService_GetEvidence_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AttestationAgentServiceServer).GetEvidence(ctx, req.(*GetEvidenceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AttestationAgentService_GetAdditionalEvidence_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetAdditionalEvidenceRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AttestationAgentServiceServer).GetAdditionalEvidence(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AttestationAgentService_GetAdditionalEvidence_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AttestationAgentServiceServer).GetAdditionalEvidence(ctx, req.(*GetAdditionalEvidenceRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AttestationAgentService_GetToken_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetTokenRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AttestationAgentServiceServer).GetToken(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AttestationAgentService_GetToken_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AttestationAgentServiceServer).GetToken(ctx, req.(*GetTokenRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AttestationAgentService_ExtendRuntimeMeasurement_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ExtendRuntimeMeasurementRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AttestationAgentServiceServer).ExtendRuntimeMeasurement(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AttestationAgentService_ExtendRuntimeMeasurement_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AttestationAgentServiceServer).ExtendRuntimeMeasurement(ctx, req.(*ExtendRuntimeMeasurementRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AttestationAgentService_BindInitData_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(BindInitDataRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AttestationAgentServiceServer).BindInitData(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AttestationAgentService_BindInitData_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AttestationAgentServiceServer).BindInitData(ctx, req.(*BindInitDataRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _AttestationAgentService_GetTeeType_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(GetTeeTypeRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(AttestationAgentServiceServer).GetTeeType(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: AttestationAgentService_GetTeeType_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(AttestationAgentServiceServer).GetTeeType(ctx, req.(*GetTeeTypeRequest)) + } + return interceptor(ctx, in, info, handler) +} + +// AttestationAgentService_ServiceDesc is the grpc.ServiceDesc for AttestationAgentService service. +// It's only intended for direct use with grpc.RegisterService, +// and not to be introspected or modified (even as a copy) +var AttestationAgentService_ServiceDesc = grpc.ServiceDesc{ + ServiceName: "attestation_agent.AttestationAgentService", + HandlerType: (*AttestationAgentServiceServer)(nil), + Methods: []grpc.MethodDesc{ + { + MethodName: "GetEvidence", + Handler: _AttestationAgentService_GetEvidence_Handler, + }, + { + MethodName: "GetAdditionalEvidence", + Handler: _AttestationAgentService_GetAdditionalEvidence_Handler, + }, + { + MethodName: "GetToken", + Handler: _AttestationAgentService_GetToken_Handler, + }, + { + MethodName: "ExtendRuntimeMeasurement", + Handler: _AttestationAgentService_ExtendRuntimeMeasurement_Handler, + }, + { + MethodName: "BindInitData", + Handler: _AttestationAgentService_BindInitData_Handler, + }, + { + MethodName: "GetTeeType", + Handler: _AttestationAgentService_GetTeeType_Handler, + }, + }, + Streams: []grpc.StreamDesc{}, + Metadata: "internal/proto/attestation-agent/attestation-agent.proto", +} diff --git a/internal/proto/attestation-agent/mocks/attestationagentserviceclient.go b/internal/proto/attestation-agent/mocks/attestationagentserviceclient.go new file mode 100644 index 00000000..ea7f7af6 --- /dev/null +++ b/internal/proto/attestation-agent/mocks/attestationagentserviceclient.go @@ -0,0 +1,565 @@ +// Copyright (c) Ultraviolet +// SPDX-License-Identifier: Apache-2.0 + +// Code generated by mockery; DO NOT EDIT. +// github.com/vektra/mockery +// template: testify + +package mocks + +import ( + "context" + + mock "github.com/stretchr/testify/mock" + "github.com/ultravioletrs/cocos/internal/proto/attestation-agent" + "google.golang.org/grpc" +) + +// NewAttestationAgentServiceClient creates a new instance of AttestationAgentServiceClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewAttestationAgentServiceClient(t interface { + mock.TestingT + Cleanup(func()) +}) *AttestationAgentServiceClient { + mock := &AttestationAgentServiceClient{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} + +// AttestationAgentServiceClient is an autogenerated mock type for the AttestationAgentServiceClient type +type AttestationAgentServiceClient struct { + mock.Mock +} + +type AttestationAgentServiceClient_Expecter struct { + mock *mock.Mock +} + +func (_m *AttestationAgentServiceClient) EXPECT() *AttestationAgentServiceClient_Expecter { + return &AttestationAgentServiceClient_Expecter{mock: &_m.Mock} +} + +// BindInitData provides a mock function for the type AttestationAgentServiceClient +func (_mock *AttestationAgentServiceClient) BindInitData(ctx context.Context, in *attestation_agent.BindInitDataRequest, opts ...grpc.CallOption) (*attestation_agent.BindInitDataResponse, error) { + // grpc.CallOption + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _mock.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for BindInitData") + } + + var r0 *attestation_agent.BindInitDataResponse + var r1 error + if returnFunc, ok := ret.Get(0).(func(context.Context, *attestation_agent.BindInitDataRequest, ...grpc.CallOption) (*attestation_agent.BindInitDataResponse, error)); ok { + return returnFunc(ctx, in, opts...) + } + if returnFunc, ok := ret.Get(0).(func(context.Context, *attestation_agent.BindInitDataRequest, ...grpc.CallOption) *attestation_agent.BindInitDataResponse); ok { + r0 = returnFunc(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*attestation_agent.BindInitDataResponse) + } + } + if returnFunc, ok := ret.Get(1).(func(context.Context, *attestation_agent.BindInitDataRequest, ...grpc.CallOption) error); ok { + r1 = returnFunc(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// AttestationAgentServiceClient_BindInitData_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'BindInitData' +type AttestationAgentServiceClient_BindInitData_Call struct { + *mock.Call +} + +// BindInitData is a helper method to define mock.On call +// - ctx context.Context +// - in *attestation_agent.BindInitDataRequest +// - opts ...grpc.CallOption +func (_e *AttestationAgentServiceClient_Expecter) BindInitData(ctx interface{}, in interface{}, opts ...interface{}) *AttestationAgentServiceClient_BindInitData_Call { + return &AttestationAgentServiceClient_BindInitData_Call{Call: _e.mock.On("BindInitData", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *AttestationAgentServiceClient_BindInitData_Call) Run(run func(ctx context.Context, in *attestation_agent.BindInitDataRequest, opts ...grpc.CallOption)) *AttestationAgentServiceClient_BindInitData_Call { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + var arg1 *attestation_agent.BindInitDataRequest + if args[1] != nil { + arg1 = args[1].(*attestation_agent.BindInitDataRequest) + } + var arg2 []grpc.CallOption + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + arg2 = variadicArgs + run( + arg0, + arg1, + arg2..., + ) + }) + return _c +} + +func (_c *AttestationAgentServiceClient_BindInitData_Call) Return(bindInitDataResponse *attestation_agent.BindInitDataResponse, err error) *AttestationAgentServiceClient_BindInitData_Call { + _c.Call.Return(bindInitDataResponse, err) + return _c +} + +func (_c *AttestationAgentServiceClient_BindInitData_Call) RunAndReturn(run func(ctx context.Context, in *attestation_agent.BindInitDataRequest, opts ...grpc.CallOption) (*attestation_agent.BindInitDataResponse, error)) *AttestationAgentServiceClient_BindInitData_Call { + _c.Call.Return(run) + return _c +} + +// ExtendRuntimeMeasurement provides a mock function for the type AttestationAgentServiceClient +func (_mock *AttestationAgentServiceClient) ExtendRuntimeMeasurement(ctx context.Context, in *attestation_agent.ExtendRuntimeMeasurementRequest, opts ...grpc.CallOption) (*attestation_agent.ExtendRuntimeMeasurementResponse, error) { + // grpc.CallOption + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _mock.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for ExtendRuntimeMeasurement") + } + + var r0 *attestation_agent.ExtendRuntimeMeasurementResponse + var r1 error + if returnFunc, ok := ret.Get(0).(func(context.Context, *attestation_agent.ExtendRuntimeMeasurementRequest, ...grpc.CallOption) (*attestation_agent.ExtendRuntimeMeasurementResponse, error)); ok { + return returnFunc(ctx, in, opts...) + } + if returnFunc, ok := ret.Get(0).(func(context.Context, *attestation_agent.ExtendRuntimeMeasurementRequest, ...grpc.CallOption) *attestation_agent.ExtendRuntimeMeasurementResponse); ok { + r0 = returnFunc(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*attestation_agent.ExtendRuntimeMeasurementResponse) + } + } + if returnFunc, ok := ret.Get(1).(func(context.Context, *attestation_agent.ExtendRuntimeMeasurementRequest, ...grpc.CallOption) error); ok { + r1 = returnFunc(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// AttestationAgentServiceClient_ExtendRuntimeMeasurement_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'ExtendRuntimeMeasurement' +type AttestationAgentServiceClient_ExtendRuntimeMeasurement_Call struct { + *mock.Call +} + +// ExtendRuntimeMeasurement is a helper method to define mock.On call +// - ctx context.Context +// - in *attestation_agent.ExtendRuntimeMeasurementRequest +// - opts ...grpc.CallOption +func (_e *AttestationAgentServiceClient_Expecter) ExtendRuntimeMeasurement(ctx interface{}, in interface{}, opts ...interface{}) *AttestationAgentServiceClient_ExtendRuntimeMeasurement_Call { + return &AttestationAgentServiceClient_ExtendRuntimeMeasurement_Call{Call: _e.mock.On("ExtendRuntimeMeasurement", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *AttestationAgentServiceClient_ExtendRuntimeMeasurement_Call) Run(run func(ctx context.Context, in *attestation_agent.ExtendRuntimeMeasurementRequest, opts ...grpc.CallOption)) *AttestationAgentServiceClient_ExtendRuntimeMeasurement_Call { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + var arg1 *attestation_agent.ExtendRuntimeMeasurementRequest + if args[1] != nil { + arg1 = args[1].(*attestation_agent.ExtendRuntimeMeasurementRequest) + } + var arg2 []grpc.CallOption + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + arg2 = variadicArgs + run( + arg0, + arg1, + arg2..., + ) + }) + return _c +} + +func (_c *AttestationAgentServiceClient_ExtendRuntimeMeasurement_Call) Return(extendRuntimeMeasurementResponse *attestation_agent.ExtendRuntimeMeasurementResponse, err error) *AttestationAgentServiceClient_ExtendRuntimeMeasurement_Call { + _c.Call.Return(extendRuntimeMeasurementResponse, err) + return _c +} + +func (_c *AttestationAgentServiceClient_ExtendRuntimeMeasurement_Call) RunAndReturn(run func(ctx context.Context, in *attestation_agent.ExtendRuntimeMeasurementRequest, opts ...grpc.CallOption) (*attestation_agent.ExtendRuntimeMeasurementResponse, error)) *AttestationAgentServiceClient_ExtendRuntimeMeasurement_Call { + _c.Call.Return(run) + return _c +} + +// GetAdditionalEvidence provides a mock function for the type AttestationAgentServiceClient +func (_mock *AttestationAgentServiceClient) GetAdditionalEvidence(ctx context.Context, in *attestation_agent.GetAdditionalEvidenceRequest, opts ...grpc.CallOption) (*attestation_agent.GetEvidenceResponse, error) { + // grpc.CallOption + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _mock.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for GetAdditionalEvidence") + } + + var r0 *attestation_agent.GetEvidenceResponse + var r1 error + if returnFunc, ok := ret.Get(0).(func(context.Context, *attestation_agent.GetAdditionalEvidenceRequest, ...grpc.CallOption) (*attestation_agent.GetEvidenceResponse, error)); ok { + return returnFunc(ctx, in, opts...) + } + if returnFunc, ok := ret.Get(0).(func(context.Context, *attestation_agent.GetAdditionalEvidenceRequest, ...grpc.CallOption) *attestation_agent.GetEvidenceResponse); ok { + r0 = returnFunc(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*attestation_agent.GetEvidenceResponse) + } + } + if returnFunc, ok := ret.Get(1).(func(context.Context, *attestation_agent.GetAdditionalEvidenceRequest, ...grpc.CallOption) error); ok { + r1 = returnFunc(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// AttestationAgentServiceClient_GetAdditionalEvidence_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetAdditionalEvidence' +type AttestationAgentServiceClient_GetAdditionalEvidence_Call struct { + *mock.Call +} + +// GetAdditionalEvidence is a helper method to define mock.On call +// - ctx context.Context +// - in *attestation_agent.GetAdditionalEvidenceRequest +// - opts ...grpc.CallOption +func (_e *AttestationAgentServiceClient_Expecter) GetAdditionalEvidence(ctx interface{}, in interface{}, opts ...interface{}) *AttestationAgentServiceClient_GetAdditionalEvidence_Call { + return &AttestationAgentServiceClient_GetAdditionalEvidence_Call{Call: _e.mock.On("GetAdditionalEvidence", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *AttestationAgentServiceClient_GetAdditionalEvidence_Call) Run(run func(ctx context.Context, in *attestation_agent.GetAdditionalEvidenceRequest, opts ...grpc.CallOption)) *AttestationAgentServiceClient_GetAdditionalEvidence_Call { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + var arg1 *attestation_agent.GetAdditionalEvidenceRequest + if args[1] != nil { + arg1 = args[1].(*attestation_agent.GetAdditionalEvidenceRequest) + } + var arg2 []grpc.CallOption + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + arg2 = variadicArgs + run( + arg0, + arg1, + arg2..., + ) + }) + return _c +} + +func (_c *AttestationAgentServiceClient_GetAdditionalEvidence_Call) Return(getEvidenceResponse *attestation_agent.GetEvidenceResponse, err error) *AttestationAgentServiceClient_GetAdditionalEvidence_Call { + _c.Call.Return(getEvidenceResponse, err) + return _c +} + +func (_c *AttestationAgentServiceClient_GetAdditionalEvidence_Call) RunAndReturn(run func(ctx context.Context, in *attestation_agent.GetAdditionalEvidenceRequest, opts ...grpc.CallOption) (*attestation_agent.GetEvidenceResponse, error)) *AttestationAgentServiceClient_GetAdditionalEvidence_Call { + _c.Call.Return(run) + return _c +} + +// GetEvidence provides a mock function for the type AttestationAgentServiceClient +func (_mock *AttestationAgentServiceClient) GetEvidence(ctx context.Context, in *attestation_agent.GetEvidenceRequest, opts ...grpc.CallOption) (*attestation_agent.GetEvidenceResponse, error) { + // grpc.CallOption + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _mock.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for GetEvidence") + } + + var r0 *attestation_agent.GetEvidenceResponse + var r1 error + if returnFunc, ok := ret.Get(0).(func(context.Context, *attestation_agent.GetEvidenceRequest, ...grpc.CallOption) (*attestation_agent.GetEvidenceResponse, error)); ok { + return returnFunc(ctx, in, opts...) + } + if returnFunc, ok := ret.Get(0).(func(context.Context, *attestation_agent.GetEvidenceRequest, ...grpc.CallOption) *attestation_agent.GetEvidenceResponse); ok { + r0 = returnFunc(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*attestation_agent.GetEvidenceResponse) + } + } + if returnFunc, ok := ret.Get(1).(func(context.Context, *attestation_agent.GetEvidenceRequest, ...grpc.CallOption) error); ok { + r1 = returnFunc(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// AttestationAgentServiceClient_GetEvidence_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetEvidence' +type AttestationAgentServiceClient_GetEvidence_Call struct { + *mock.Call +} + +// GetEvidence is a helper method to define mock.On call +// - ctx context.Context +// - in *attestation_agent.GetEvidenceRequest +// - opts ...grpc.CallOption +func (_e *AttestationAgentServiceClient_Expecter) GetEvidence(ctx interface{}, in interface{}, opts ...interface{}) *AttestationAgentServiceClient_GetEvidence_Call { + return &AttestationAgentServiceClient_GetEvidence_Call{Call: _e.mock.On("GetEvidence", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *AttestationAgentServiceClient_GetEvidence_Call) Run(run func(ctx context.Context, in *attestation_agent.GetEvidenceRequest, opts ...grpc.CallOption)) *AttestationAgentServiceClient_GetEvidence_Call { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + var arg1 *attestation_agent.GetEvidenceRequest + if args[1] != nil { + arg1 = args[1].(*attestation_agent.GetEvidenceRequest) + } + var arg2 []grpc.CallOption + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + arg2 = variadicArgs + run( + arg0, + arg1, + arg2..., + ) + }) + return _c +} + +func (_c *AttestationAgentServiceClient_GetEvidence_Call) Return(getEvidenceResponse *attestation_agent.GetEvidenceResponse, err error) *AttestationAgentServiceClient_GetEvidence_Call { + _c.Call.Return(getEvidenceResponse, err) + return _c +} + +func (_c *AttestationAgentServiceClient_GetEvidence_Call) RunAndReturn(run func(ctx context.Context, in *attestation_agent.GetEvidenceRequest, opts ...grpc.CallOption) (*attestation_agent.GetEvidenceResponse, error)) *AttestationAgentServiceClient_GetEvidence_Call { + _c.Call.Return(run) + return _c +} + +// GetTeeType provides a mock function for the type AttestationAgentServiceClient +func (_mock *AttestationAgentServiceClient) GetTeeType(ctx context.Context, in *attestation_agent.GetTeeTypeRequest, opts ...grpc.CallOption) (*attestation_agent.GetTeeTypeResponse, error) { + // grpc.CallOption + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _mock.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for GetTeeType") + } + + var r0 *attestation_agent.GetTeeTypeResponse + var r1 error + if returnFunc, ok := ret.Get(0).(func(context.Context, *attestation_agent.GetTeeTypeRequest, ...grpc.CallOption) (*attestation_agent.GetTeeTypeResponse, error)); ok { + return returnFunc(ctx, in, opts...) + } + if returnFunc, ok := ret.Get(0).(func(context.Context, *attestation_agent.GetTeeTypeRequest, ...grpc.CallOption) *attestation_agent.GetTeeTypeResponse); ok { + r0 = returnFunc(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*attestation_agent.GetTeeTypeResponse) + } + } + if returnFunc, ok := ret.Get(1).(func(context.Context, *attestation_agent.GetTeeTypeRequest, ...grpc.CallOption) error); ok { + r1 = returnFunc(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// AttestationAgentServiceClient_GetTeeType_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetTeeType' +type AttestationAgentServiceClient_GetTeeType_Call struct { + *mock.Call +} + +// GetTeeType is a helper method to define mock.On call +// - ctx context.Context +// - in *attestation_agent.GetTeeTypeRequest +// - opts ...grpc.CallOption +func (_e *AttestationAgentServiceClient_Expecter) GetTeeType(ctx interface{}, in interface{}, opts ...interface{}) *AttestationAgentServiceClient_GetTeeType_Call { + return &AttestationAgentServiceClient_GetTeeType_Call{Call: _e.mock.On("GetTeeType", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *AttestationAgentServiceClient_GetTeeType_Call) Run(run func(ctx context.Context, in *attestation_agent.GetTeeTypeRequest, opts ...grpc.CallOption)) *AttestationAgentServiceClient_GetTeeType_Call { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + var arg1 *attestation_agent.GetTeeTypeRequest + if args[1] != nil { + arg1 = args[1].(*attestation_agent.GetTeeTypeRequest) + } + var arg2 []grpc.CallOption + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + arg2 = variadicArgs + run( + arg0, + arg1, + arg2..., + ) + }) + return _c +} + +func (_c *AttestationAgentServiceClient_GetTeeType_Call) Return(getTeeTypeResponse *attestation_agent.GetTeeTypeResponse, err error) *AttestationAgentServiceClient_GetTeeType_Call { + _c.Call.Return(getTeeTypeResponse, err) + return _c +} + +func (_c *AttestationAgentServiceClient_GetTeeType_Call) RunAndReturn(run func(ctx context.Context, in *attestation_agent.GetTeeTypeRequest, opts ...grpc.CallOption) (*attestation_agent.GetTeeTypeResponse, error)) *AttestationAgentServiceClient_GetTeeType_Call { + _c.Call.Return(run) + return _c +} + +// GetToken provides a mock function for the type AttestationAgentServiceClient +func (_mock *AttestationAgentServiceClient) GetToken(ctx context.Context, in *attestation_agent.GetTokenRequest, opts ...grpc.CallOption) (*attestation_agent.GetTokenResponse, error) { + // grpc.CallOption + _va := make([]interface{}, len(opts)) + for _i := range opts { + _va[_i] = opts[_i] + } + var _ca []interface{} + _ca = append(_ca, ctx, in) + _ca = append(_ca, _va...) + ret := _mock.Called(_ca...) + + if len(ret) == 0 { + panic("no return value specified for GetToken") + } + + var r0 *attestation_agent.GetTokenResponse + var r1 error + if returnFunc, ok := ret.Get(0).(func(context.Context, *attestation_agent.GetTokenRequest, ...grpc.CallOption) (*attestation_agent.GetTokenResponse, error)); ok { + return returnFunc(ctx, in, opts...) + } + if returnFunc, ok := ret.Get(0).(func(context.Context, *attestation_agent.GetTokenRequest, ...grpc.CallOption) *attestation_agent.GetTokenResponse); ok { + r0 = returnFunc(ctx, in, opts...) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*attestation_agent.GetTokenResponse) + } + } + if returnFunc, ok := ret.Get(1).(func(context.Context, *attestation_agent.GetTokenRequest, ...grpc.CallOption) error); ok { + r1 = returnFunc(ctx, in, opts...) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// AttestationAgentServiceClient_GetToken_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'GetToken' +type AttestationAgentServiceClient_GetToken_Call struct { + *mock.Call +} + +// GetToken is a helper method to define mock.On call +// - ctx context.Context +// - in *attestation_agent.GetTokenRequest +// - opts ...grpc.CallOption +func (_e *AttestationAgentServiceClient_Expecter) GetToken(ctx interface{}, in interface{}, opts ...interface{}) *AttestationAgentServiceClient_GetToken_Call { + return &AttestationAgentServiceClient_GetToken_Call{Call: _e.mock.On("GetToken", + append([]interface{}{ctx, in}, opts...)...)} +} + +func (_c *AttestationAgentServiceClient_GetToken_Call) Run(run func(ctx context.Context, in *attestation_agent.GetTokenRequest, opts ...grpc.CallOption)) *AttestationAgentServiceClient_GetToken_Call { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + var arg1 *attestation_agent.GetTokenRequest + if args[1] != nil { + arg1 = args[1].(*attestation_agent.GetTokenRequest) + } + var arg2 []grpc.CallOption + variadicArgs := make([]grpc.CallOption, len(args)-2) + for i, a := range args[2:] { + if a != nil { + variadicArgs[i] = a.(grpc.CallOption) + } + } + arg2 = variadicArgs + run( + arg0, + arg1, + arg2..., + ) + }) + return _c +} + +func (_c *AttestationAgentServiceClient_GetToken_Call) Return(getTokenResponse *attestation_agent.GetTokenResponse, err error) *AttestationAgentServiceClient_GetToken_Call { + _c.Call.Return(getTokenResponse, err) + return _c +} + +func (_c *AttestationAgentServiceClient_GetToken_Call) RunAndReturn(run func(ctx context.Context, in *attestation_agent.GetTokenRequest, opts ...grpc.CallOption) (*attestation_agent.GetTokenResponse, error)) *AttestationAgentServiceClient_GetToken_Call { + _c.Call.Return(run) + return _c +} diff --git a/internal/proto/attestation/v1/attestation.pb.go b/internal/proto/attestation/v1/attestation.pb.go index 18560e9a..af24a194 100644 --- a/internal/proto/attestation/v1/attestation.pb.go +++ b/internal/proto/attestation/v1/attestation.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.8 +// protoc-gen-go v1.36.11 // protoc v6.33.1 // source: internal/proto/attestation/v1/attestation.proto diff --git a/internal/proto/attestation/v1/attestation_grpc.pb.go b/internal/proto/attestation/v1/attestation_grpc.pb.go index dc343d56..5d4dbc87 100644 --- a/internal/proto/attestation/v1/attestation_grpc.pb.go +++ b/internal/proto/attestation/v1/attestation_grpc.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.5.1 +// - protoc-gen-go-grpc v1.6.0 // - protoc v6.33.1 // source: internal/proto/attestation/v1/attestation.proto @@ -76,10 +76,10 @@ type AttestationServiceServer interface { type UnimplementedAttestationServiceServer struct{} func (UnimplementedAttestationServiceServer) FetchAttestation(context.Context, *AttestationRequest) (*AttestationResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method FetchAttestation not implemented") + return nil, status.Error(codes.Unimplemented, "method FetchAttestation not implemented") } func (UnimplementedAttestationServiceServer) FetchAzureToken(context.Context, *AzureTokenRequest) (*AzureTokenResponse, error) { - return nil, status.Errorf(codes.Unimplemented, "method FetchAzureToken not implemented") + return nil, status.Error(codes.Unimplemented, "method FetchAzureToken not implemented") } func (UnimplementedAttestationServiceServer) mustEmbedUnimplementedAttestationServiceServer() {} func (UnimplementedAttestationServiceServer) testEmbeddedByValue() {} @@ -92,7 +92,7 @@ type UnsafeAttestationServiceServer interface { } func RegisterAttestationServiceServer(s grpc.ServiceRegistrar, srv AttestationServiceServer) { - // If the following call pancis, it indicates UnimplementedAttestationServiceServer was + // If the following call panics, it indicates UnimplementedAttestationServiceServer was // embedded by pointer and is nil. This will cause panics if an // unimplemented method is ever invoked, so we test this at initialization // time to prevent it from happening at runtime later due to I/O. diff --git a/manager/manager.pb.go b/manager/manager.pb.go index 425c6162..40455970 100644 --- a/manager/manager.pb.go +++ b/manager/manager.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.36.8 +// protoc-gen-go v1.36.11 // protoc v6.33.1 // source: manager/manager.proto diff --git a/manager/manager_grpc.pb.go b/manager/manager_grpc.pb.go index 6fc3a894..dd5c1ffb 100644 --- a/manager/manager_grpc.pb.go +++ b/manager/manager_grpc.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.5.1 +// - protoc-gen-go-grpc v1.6.0 // - protoc v6.33.1 // source: manager/manager.proto @@ -106,16 +106,16 @@ type ManagerServiceServer interface { type UnimplementedManagerServiceServer struct{} func (UnimplementedManagerServiceServer) CreateVm(context.Context, *CreateReq) (*CreateRes, error) { - return nil, status.Errorf(codes.Unimplemented, "method CreateVm not implemented") + return nil, status.Error(codes.Unimplemented, "method CreateVm not implemented") } func (UnimplementedManagerServiceServer) RemoveVm(context.Context, *RemoveReq) (*emptypb.Empty, error) { - return nil, status.Errorf(codes.Unimplemented, "method RemoveVm not implemented") + return nil, status.Error(codes.Unimplemented, "method RemoveVm not implemented") } func (UnimplementedManagerServiceServer) CVMInfo(context.Context, *CVMInfoReq) (*CVMInfoRes, error) { - return nil, status.Errorf(codes.Unimplemented, "method CVMInfo not implemented") + return nil, status.Error(codes.Unimplemented, "method CVMInfo not implemented") } func (UnimplementedManagerServiceServer) AttestationPolicy(context.Context, *AttestationPolicyReq) (*AttestationPolicyRes, error) { - return nil, status.Errorf(codes.Unimplemented, "method AttestationPolicy not implemented") + return nil, status.Error(codes.Unimplemented, "method AttestationPolicy not implemented") } func (UnimplementedManagerServiceServer) mustEmbedUnimplementedManagerServiceServer() {} func (UnimplementedManagerServiceServer) testEmbeddedByValue() {} @@ -128,7 +128,7 @@ type UnsafeManagerServiceServer interface { } func RegisterManagerServiceServer(s grpc.ServiceRegistrar, srv ManagerServiceServer) { - // If the following call pancis, it indicates UnimplementedManagerServiceServer was + // If the following call panics, it indicates UnimplementedManagerServiceServer was // embedded by pointer and is nil. This will cause panics if an // unimplemented method is ever invoked, so we test this at initialization // time to prevent it from happening at runtime later due to I/O. diff --git a/pkg/attestation/ccaa/provider.go b/pkg/attestation/ccaa/provider.go new file mode 100644 index 00000000..6dc7cdc4 --- /dev/null +++ b/pkg/attestation/ccaa/provider.go @@ -0,0 +1,131 @@ +// Copyright (c) Ultraviolet +// SPDX-License-Identifier: Apache-2.0 +package ccaa + +import ( + "context" + "fmt" + "time" + + attestation_agent "github.com/ultravioletrs/cocos/internal/proto/attestation-agent" + "google.golang.org/grpc" + "google.golang.org/grpc/credentials/insecure" +) + +// Provider implements attestation.Provider interface by delegating to CC attestation-agent. +type Provider struct { + client attestation_agent.AttestationAgentServiceClient + conn *grpc.ClientConn + addr string +} + +// NewProvider creates a new CC attestation-agent provider. +// addr should be in the format "host:port" (e.g., "127.0.0.1:50002"). +func NewProvider(addr string) (*Provider, error) { + conn, err := grpc.NewClient(addr, grpc.WithTransportCredentials(insecure.NewCredentials())) + if err != nil { + return nil, fmt.Errorf("failed to connect to CC attestation-agent at %s: %w", addr, err) + } + + client := attestation_agent.NewAttestationAgentServiceClient(conn) + + // Test connection by getting TEE type + ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + + _, err = client.GetTeeType(ctx, &attestation_agent.GetTeeTypeRequest{}) + if err != nil { + conn.Close() + return nil, fmt.Errorf("failed to verify CC attestation-agent connection: %w", err) + } + + return &Provider{ + client: client, + conn: conn, + addr: addr, + }, nil +} + +// Close closes the gRPC connection to CC attestation-agent. +func (p *Provider) Close() error { + if p.conn != nil { + return p.conn.Close() + } + return nil +} + +// TeeAttestation retrieves TEE attestation evidence using report data. +// For TDX/SNP, reportData should be 64 bytes. +func (p *Provider) TeeAttestation(reportData []byte) ([]byte, error) { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + resp, err := p.client.GetEvidence(ctx, &attestation_agent.GetEvidenceRequest{ + RuntimeData: reportData, + }) + if err != nil { + return nil, fmt.Errorf("CC attestation-agent GetEvidence failed: %w", err) + } + + return resp.Evidence, nil +} + +// VTpmAttestation retrieves vTPM attestation evidence using nonce. +// For vTPM, nonce should be 32 bytes. +func (p *Provider) VTpmAttestation(nonce []byte) ([]byte, error) { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + resp, err := p.client.GetEvidence(ctx, &attestation_agent.GetEvidenceRequest{ + RuntimeData: nonce, + }) + if err != nil { + return nil, fmt.Errorf("CC attestation-agent GetEvidence failed: %w", err) + } + + return resp.Evidence, nil +} + +// Attestation retrieves combined attestation evidence using both report data and nonce. +// This is used for SNP+vTPM scenarios. +func (p *Provider) Attestation(reportData []byte, nonce []byte) ([]byte, error) { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + // Combine reportData and nonce into RuntimeData + runtimeData := append(reportData, nonce...) + + resp, err := p.client.GetEvidence(ctx, &attestation_agent.GetEvidenceRequest{ + RuntimeData: runtimeData, + }) + if err != nil { + return nil, fmt.Errorf("CC attestation-agent GetEvidence failed: %w", err) + } + + return resp.Evidence, nil +} + +// AzureAttestationToken retrieves Azure-specific attestation token. +// Note: CC attestation-agent may not support Azure tokens in the same way. +// This implementation attempts to use GetToken with "Azure" token type. +func (p *Provider) AzureAttestationToken(nonce []byte) ([]byte, error) { + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + defer cancel() + + // Try to get Azure token via GetToken method + resp, err := p.client.GetToken(ctx, &attestation_agent.GetTokenRequest{ + TokenType: "Azure", + }) + if err != nil { + // Fallback: try GetEvidence with nonce + evidenceResp, evidenceErr := p.client.GetEvidence(ctx, &attestation_agent.GetEvidenceRequest{ + RuntimeData: nonce, + }) + if evidenceErr != nil { + return nil, fmt.Errorf("CC attestation-agent Azure token not supported: GetToken failed: %w, GetEvidence fallback failed: %v", err, evidenceErr) + } + return evidenceResp.Evidence, nil + } + + return resp.Token, nil +} diff --git a/pkg/attestation/ccaa/provider_test.go b/pkg/attestation/ccaa/provider_test.go new file mode 100644 index 00000000..4edf856e --- /dev/null +++ b/pkg/attestation/ccaa/provider_test.go @@ -0,0 +1,325 @@ +// Copyright (c) Ultraviolet +// SPDX-License-Identifier: Apache-2.0 +package ccaa + +import ( + "context" + "testing" + + "github.com/stretchr/testify/mock" + attestation_agent "github.com/ultravioletrs/cocos/internal/proto/attestation-agent" + "github.com/ultravioletrs/cocos/internal/proto/attestation-agent/mocks" +) + +// TestTeeAttestationSuccess tests successful TDX attestation. +func TestTeeAttestationSuccess(t *testing.T) { + mockClient := mocks.NewAttestationAgentServiceClient(t) + mockClient.EXPECT(). + GetEvidence(mock.MatchedBy(func(ctx context.Context) bool { + return ctx != nil + }), mock.MatchedBy(func(req *attestation_agent.GetEvidenceRequest) bool { + return len(req.RuntimeData) == 64 + })). + Return(&attestation_agent.GetEvidenceResponse{ + Evidence: []byte("test_evidence"), + }, nil) + + provider := &Provider{client: mockClient, conn: nil, addr: "localhost:50002"} + evidence, err := provider.TeeAttestation(make([]byte, 64)) + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + if string(evidence) != "test_evidence" { + t.Fatalf("expected 'test_evidence', got '%s'", string(evidence)) + } +} + +// TestVTpmAttestationSuccess tests successful vTPM attestation. +func TestVTpmAttestationSuccess(t *testing.T) { + mockClient := mocks.NewAttestationAgentServiceClient(t) + mockClient.EXPECT(). + GetEvidence(mock.MatchedBy(func(ctx context.Context) bool { + return ctx != nil + }), mock.MatchedBy(func(req *attestation_agent.GetEvidenceRequest) bool { + return len(req.RuntimeData) == 32 + })). + Return(&attestation_agent.GetEvidenceResponse{ + Evidence: []byte("vtpm_evidence"), + }, nil) + + provider := &Provider{client: mockClient, conn: nil, addr: "localhost:50002"} + evidence, err := provider.VTpmAttestation(make([]byte, 32)) + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + if string(evidence) != "vtpm_evidence" { + t.Fatalf("expected 'vtpm_evidence', got '%s'", string(evidence)) + } +} + +// TestAttestationSuccess tests combined SNP+vTPM attestation. +func TestAttestationSuccess(t *testing.T) { + mockClient := mocks.NewAttestationAgentServiceClient(t) + mockClient.EXPECT(). + GetEvidence(mock.MatchedBy(func(ctx context.Context) bool { + return ctx != nil + }), mock.MatchedBy(func(req *attestation_agent.GetEvidenceRequest) bool { + return len(req.RuntimeData) == 96 // 64 + 32 + })). + Return(&attestation_agent.GetEvidenceResponse{ + Evidence: []byte("combined_evidence"), + }, nil) + + provider := &Provider{client: mockClient, conn: nil, addr: "localhost:50002"} + evidence, err := provider.Attestation(make([]byte, 64), make([]byte, 32)) + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + if string(evidence) != "combined_evidence" { + t.Fatalf("expected 'combined_evidence', got '%s'", string(evidence)) + } +} + +// TestAzureTokenSuccess tests Azure token retrieval via GetToken. +func TestAzureTokenSuccess(t *testing.T) { + mockClient := mocks.NewAttestationAgentServiceClient(t) + mockClient.EXPECT(). + GetToken(mock.MatchedBy(func(ctx context.Context) bool { + return ctx != nil + }), mock.MatchedBy(func(req *attestation_agent.GetTokenRequest) bool { + return req.TokenType == "Azure" + })). + Return(&attestation_agent.GetTokenResponse{ + Token: []byte("azure_token"), + }, nil) + + provider := &Provider{client: mockClient, conn: nil, addr: "localhost:50002"} + token, err := provider.AzureAttestationToken(make([]byte, 32)) + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + if string(token) != "azure_token" { + t.Fatalf("expected 'azure_token', got '%s'", string(token)) + } +} + +// TestAzureTokenFallback tests fallback from GetToken to GetEvidence. +func TestAzureTokenFallback(t *testing.T) { + mockClient := mocks.NewAttestationAgentServiceClient(t) + + // GetToken fails + mockClient.EXPECT(). + GetToken(mock.Anything, mock.Anything). + Return(nil, context.DeadlineExceeded).Once() + + // Fallback to GetEvidence + mockClient.EXPECT(). + GetEvidence(mock.MatchedBy(func(ctx context.Context) bool { + return ctx != nil + }), mock.Anything). + Return(&attestation_agent.GetEvidenceResponse{ + Evidence: []byte("fallback_evidence"), + }, nil) + + provider := &Provider{client: mockClient, conn: nil, addr: "localhost:50002"} + evidence, err := provider.AzureAttestationToken(make([]byte, 32)) + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + if string(evidence) != "fallback_evidence" { + t.Fatalf("expected 'fallback_evidence', got '%s'", string(evidence)) + } +} + +// TestTeeAttestationError tests error handling in TeeAttestation. +func TestTeeAttestationError(t *testing.T) { + mockClient := mocks.NewAttestationAgentServiceClient(t) + mockClient.EXPECT(). + GetEvidence(mock.Anything, mock.Anything). + Return(nil, context.DeadlineExceeded) + + provider := &Provider{client: mockClient, conn: nil, addr: "localhost:50002"} + _, err := provider.TeeAttestation(make([]byte, 64)) + + if err == nil { + t.Fatal("expected error, got nil") + } +} + +// TestVTpmAttestationError tests error handling in VTpmAttestation. +func TestVTpmAttestationError(t *testing.T) { + mockClient := mocks.NewAttestationAgentServiceClient(t) + mockClient.EXPECT(). + GetEvidence(mock.Anything, mock.Anything). + Return(nil, context.DeadlineExceeded) + + provider := &Provider{client: mockClient, conn: nil, addr: "localhost:50002"} + _, err := provider.VTpmAttestation(make([]byte, 32)) + + if err == nil { + t.Fatal("expected error, got nil") + } +} + +// TestAzureTokenBothFail tests error when both GetToken and GetEvidence fail. +func TestAzureTokenBothFail(t *testing.T) { + mockClient := mocks.NewAttestationAgentServiceClient(t) + + mockClient.EXPECT(). + GetToken(mock.Anything, mock.Anything). + Return(nil, context.DeadlineExceeded).Once() + + mockClient.EXPECT(). + GetEvidence(mock.Anything, mock.Anything). + Return(nil, context.DeadlineExceeded) + + provider := &Provider{client: mockClient, conn: nil, addr: "localhost:50002"} + _, err := provider.AzureAttestationToken(make([]byte, 32)) + + if err == nil { + t.Fatal("expected error, got nil") + } +} + +// TestCloseWithNilConnection tests Close with nil connection. +func TestCloseWithNilConnection(t *testing.T) { + provider := &Provider{conn: nil} + err := provider.Close() + if err != nil { + t.Fatalf("expected no error, got %v", err) + } +} + +// TestProviderFields tests provider field initialization. +func TestProviderFields(t *testing.T) { + mockClient := mocks.NewAttestationAgentServiceClient(t) + addr := "localhost:50002" + + provider := &Provider{ + client: mockClient, + conn: nil, + addr: addr, + } + + if provider.addr != addr { + t.Fatalf("expected addr '%s', got '%s'", addr, provider.addr) + } + if provider.client != mockClient { + t.Fatal("client mismatch") + } +} + +// TestEmptyReportData tests TeeAttestation with empty data. +func TestEmptyReportData(t *testing.T) { + mockClient := mocks.NewAttestationAgentServiceClient(t) + mockClient.EXPECT(). + GetEvidence(mock.Anything, mock.MatchedBy(func(req *attestation_agent.GetEvidenceRequest) bool { + return len(req.RuntimeData) == 0 + })). + Return(&attestation_agent.GetEvidenceResponse{ + Evidence: []byte("empty_data_evidence"), + }, nil) + + provider := &Provider{client: mockClient, conn: nil, addr: "localhost:50002"} + evidence, err := provider.TeeAttestation([]byte{}) + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + if string(evidence) != "empty_data_evidence" { + t.Fatalf("expected 'empty_data_evidence', got '%s'", string(evidence)) + } +} + +// TestLargeReportData tests TeeAttestation with large data. +func TestLargeReportData(t *testing.T) { + mockClient := mocks.NewAttestationAgentServiceClient(t) + mockClient.EXPECT(). + GetEvidence(mock.Anything, mock.MatchedBy(func(req *attestation_agent.GetEvidenceRequest) bool { + return len(req.RuntimeData) == 10000 + })). + Return(&attestation_agent.GetEvidenceResponse{ + Evidence: []byte("large_data_evidence"), + }, nil) + + provider := &Provider{client: mockClient, conn: nil, addr: "localhost:50002"} + evidence, err := provider.TeeAttestation(make([]byte, 10000)) + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + if string(evidence) != "large_data_evidence" { + t.Fatalf("expected 'large_data_evidence', got '%s'", string(evidence)) + } +} + +// TestDataConcatenationInAttestation tests data concatenation. +func TestDataConcatenationInAttestation(t *testing.T) { + mockClient := mocks.NewAttestationAgentServiceClient(t) + mockClient.EXPECT(). + GetEvidence(mock.Anything, mock.MatchedBy(func(req *attestation_agent.GetEvidenceRequest) bool { + // Verify data was concatenated correctly + expected := []byte{1, 2, 3, 4, 5, 6} + return len(req.RuntimeData) == len(expected) + })). + Return(&attestation_agent.GetEvidenceResponse{ + Evidence: []byte("concat_evidence"), + }, nil) + + provider := &Provider{client: mockClient, conn: nil, addr: "localhost:50002"} + evidence, err := provider.Attestation([]byte{1, 2, 3}, []byte{4, 5, 6}) + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + if string(evidence) != "concat_evidence" { + t.Fatalf("expected 'concat_evidence', got '%s'", string(evidence)) + } +} + +// TestMultipleCalls tests multiple successive calls. +func TestMultipleCalls(t *testing.T) { + mockClient := mocks.NewAttestationAgentServiceClient(t) + + // Expect 3 calls + for i := 0; i < 3; i++ { + mockClient.EXPECT(). + GetEvidence(mock.Anything, mock.Anything). + Return(&attestation_agent.GetEvidenceResponse{ + Evidence: []byte("evidence"), + }, nil).Once() + } + + provider := &Provider{client: mockClient, conn: nil, addr: "localhost:50002"} + + for i := 0; i < 3; i++ { + evidence, err := provider.TeeAttestation(make([]byte, 64)) + if err != nil { + t.Fatalf("iteration %d: expected no error, got %v", i, err) + } + if string(evidence) != "evidence" { + t.Fatalf("iteration %d: expected 'evidence', got '%s'", i, string(evidence)) + } + } +} + +// TestEvidencePreservation tests that evidence data is preserved. +func TestEvidencePreservation(t *testing.T) { + mockClient := mocks.NewAttestationAgentServiceClient(t) + expectedBytes := []byte{0xFF, 0xEE, 0xDD, 0xCC} + + mockClient.EXPECT(). + GetEvidence(mock.Anything, mock.Anything). + Return(&attestation_agent.GetEvidenceResponse{ + Evidence: expectedBytes, + }, nil) + + provider := &Provider{client: mockClient, conn: nil, addr: "localhost:50002"} + evidence, err := provider.TeeAttestation(make([]byte, 64)) + if err != nil { + t.Fatalf("expected no error, got %v", err) + } + + for i, b := range evidence { + if b != expectedBytes[i] { + t.Fatalf("byte mismatch at index %d: expected 0x%02x, got 0x%02x", i, expectedBytes[i], b) + } + } +}