Compare commits

..

3 Commits

Author SHA1 Message Date
Sammy Kerata Oina c14f1d7b6c COCOS-391- GCP Attestation policy (#405)
* Add AgentGrpcHost configuration to agent server

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

* Add SHA1 support to PcrValues and implement GCP attestation functions

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

* Add GCP attestation policy and OVMF download commands

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

* Add vTPM attestation support and update protobuf versions

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

* Remove Host field from AgentConfig and update related references

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

* Update GCP attestation policy to accept vCPU count as an argument

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

* Add SHA512 digest verification for OVMF file in GCP download command

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

* Update OVMF object name format in GCP attestation package

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

* Refactor attestation policy structure to use nested Config field

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

---------

Signed-off-by: Sammy Oina <sammyoina@gmail.com>
2025-03-19 09:39:46 +01:00
Danko Miladinovic ebc8f1bba4 NOISSUE - Update documentation for vTPM changes (#408)
* change readme according to vTPM changes

* rebase
2025-03-19 09:38:48 +01:00
Danko Miladinovic 293c65a3aa NOISSUE - Add path to expected PCR values (#398)
CI / ci (push) Has been cancelled
Rust CI Pipeline / rust-check (push) Has been cancelled
* add path to expected PCR values

* change rust scrtip for attestation policy to print policy to stdout

* fix cli test

* remove stdout from cmd config struct

* fix manager test

* fix manager readme
2025-03-17 12:25:42 +01:00
41 changed files with 1166 additions and 478 deletions
+2 -2
View File
@@ -33,8 +33,8 @@ jobs:
- name: Set up protoc
run: |
PROTOC_VERSION=29.3
PROTOC_GEN_VERSION=v1.36.4
PROTOC_VERSION=29.0
PROTOC_GEN_VERSION=v1.36.5
PROTOC_GRPC_VERSION=v1.5.1
# Download and install protoc
+2 -2
View File
@@ -3,8 +3,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.4
// protoc v5.29.3
// protoc-gen-go v1.36.5
// protoc v5.29.0
// source: agent/agent.proto
package agent
+1 -1
View File
@@ -4,7 +4,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v5.29.3
// - protoc v5.29.0
// source: agent/agent.proto
package agent
-1
View File
@@ -13,7 +13,6 @@ import (
var _ fmt.Stringer = (*Datasets)(nil)
type AgentConfig struct {
Host string `json:"host,omitempty"`
Port string `json:"port,omitempty"`
CertFile string `json:"cert_file,omitempty"`
KeyFile string `json:"server_key,omitempty"`
-1
View File
@@ -106,7 +106,6 @@ func TestDecompressToContext(t *testing.T) {
func TestAgentConfigJSON(t *testing.T) {
config := AgentConfig{
Host: "localhost",
Port: "8080",
CertFile: "cert.pem",
KeyFile: "key.pem",
-1
View File
@@ -253,7 +253,6 @@ func (client *CVMSClient) executeRun(ctx context.Context, runReq *cvms.Computati
if err := client.sp.Start(agent.AgentConfig{
Port: runReq.AgentConfig.Port,
Host: runReq.AgentConfig.Host,
CertFile: runReq.AgentConfig.CertFile,
KeyFile: runReq.AgentConfig.KeyFile,
ServerCAFile: runReq.AgentConfig.ServerCaFile,
+191 -118
View File
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.0
// protoc-gen-go v1.36.5
// protoc v5.29.0
// source: agent/cvms/cvms.proto
@@ -15,6 +15,7 @@ import (
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -429,6 +430,7 @@ type ClientStreamMessage struct {
// *ClientStreamMessage_RunRes
// *ClientStreamMessage_StopComputationRes
// *ClientStreamMessage_AgentStateRes
// *ClientStreamMessage_VTPMattestationReport
Message isClientStreamMessage_Message `protobuf_oneof:"message"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
@@ -516,6 +518,15 @@ func (x *ClientStreamMessage) GetAgentStateRes() *AgentStateRes {
return nil
}
func (x *ClientStreamMessage) GetVTPMattestationReport() *AttestationResponse {
if x != nil {
if x, ok := x.Message.(*ClientStreamMessage_VTPMattestationReport); ok {
return x.VTPMattestationReport
}
}
return nil
}
type isClientStreamMessage_Message interface {
isClientStreamMessage_Message()
}
@@ -540,6 +551,10 @@ type ClientStreamMessage_AgentStateRes struct {
AgentStateRes *AgentStateRes `protobuf:"bytes,5,opt,name=agentStateRes,proto3,oneof"`
}
type ClientStreamMessage_VTPMattestationReport struct {
VTPMattestationReport *AttestationResponse `protobuf:"bytes,6,opt,name=vTPMattestationReport,proto3,oneof"`
}
func (*ClientStreamMessage_AgentLog) isClientStreamMessage_Message() {}
func (*ClientStreamMessage_AgentEvent) isClientStreamMessage_Message() {}
@@ -550,6 +565,8 @@ func (*ClientStreamMessage_StopComputationRes) isClientStreamMessage_Message() {
func (*ClientStreamMessage_AgentStateRes) isClientStreamMessage_Message() {}
func (*ClientStreamMessage_VTPMattestationReport) isClientStreamMessage_Message() {}
type ServerStreamMessage struct {
state protoimpl.MessageState `protogen:"open.v1"`
// Types that are valid to be assigned to Message:
@@ -975,13 +992,12 @@ func (x *Algorithm) GetUserKey() []byte {
type AgentConfig struct {
state protoimpl.MessageState `protogen:"open.v1"`
Port string `protobuf:"bytes,1,opt,name=port,proto3" json:"port,omitempty"`
Host string `protobuf:"bytes,2,opt,name=host,proto3" json:"host,omitempty"`
CertFile string `protobuf:"bytes,3,opt,name=cert_file,json=certFile,proto3" json:"cert_file,omitempty"`
KeyFile string `protobuf:"bytes,4,opt,name=key_file,json=keyFile,proto3" json:"key_file,omitempty"`
ClientCaFile string `protobuf:"bytes,5,opt,name=client_ca_file,json=clientCaFile,proto3" json:"client_ca_file,omitempty"`
ServerCaFile string `protobuf:"bytes,6,opt,name=server_ca_file,json=serverCaFile,proto3" json:"server_ca_file,omitempty"`
LogLevel string `protobuf:"bytes,7,opt,name=log_level,json=logLevel,proto3" json:"log_level,omitempty"`
AttestedTls bool `protobuf:"varint,8,opt,name=attested_tls,json=attestedTls,proto3" json:"attested_tls,omitempty"`
CertFile string `protobuf:"bytes,2,opt,name=cert_file,json=certFile,proto3" json:"cert_file,omitempty"`
KeyFile string `protobuf:"bytes,3,opt,name=key_file,json=keyFile,proto3" json:"key_file,omitempty"`
ClientCaFile string `protobuf:"bytes,4,opt,name=client_ca_file,json=clientCaFile,proto3" json:"client_ca_file,omitempty"`
ServerCaFile string `protobuf:"bytes,5,opt,name=server_ca_file,json=serverCaFile,proto3" json:"server_ca_file,omitempty"`
LogLevel string `protobuf:"bytes,6,opt,name=log_level,json=logLevel,proto3" json:"log_level,omitempty"`
AttestedTls bool `protobuf:"varint,7,opt,name=attested_tls,json=attestedTls,proto3" json:"attested_tls,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@@ -1023,13 +1039,6 @@ func (x *AgentConfig) GetPort() string {
return ""
}
func (x *AgentConfig) GetHost() string {
if x != nil {
return x.Host
}
return ""
}
func (x *AgentConfig) GetCertFile() string {
if x != nil {
return x.CertFile
@@ -1072,9 +1081,61 @@ func (x *AgentConfig) GetAttestedTls() bool {
return false
}
type AttestationResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
File []byte `protobuf:"bytes,1,opt,name=file,proto3" json:"file,omitempty"`
CertSerialNumber string `protobuf:"bytes,2,opt,name=certSerialNumber,proto3" json:"certSerialNumber,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *AttestationResponse) Reset() {
*x = AttestationResponse{}
mi := &file_agent_cvms_cvms_proto_msgTypes[15]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *AttestationResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*AttestationResponse) ProtoMessage() {}
func (x *AttestationResponse) ProtoReflect() protoreflect.Message {
mi := &file_agent_cvms_cvms_proto_msgTypes[15]
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 AttestationResponse.ProtoReflect.Descriptor instead.
func (*AttestationResponse) Descriptor() ([]byte, []int) {
return file_agent_cvms_cvms_proto_rawDescGZIP(), []int{15}
}
func (x *AttestationResponse) GetFile() []byte {
if x != nil {
return x.File
}
return nil
}
func (x *AttestationResponse) GetCertSerialNumber() string {
if x != nil {
return x.CertSerialNumber
}
return ""
}
var File_agent_cvms_cvms_proto protoreflect.FileDescriptor
var file_agent_cvms_cvms_proto_rawDesc = []byte{
var file_agent_cvms_cvms_proto_rawDesc = string([]byte{
0x0a, 0x15, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x76, 0x6d, 0x73, 0x2f, 0x63, 0x76, 0x6d,
0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x63, 0x76, 0x6d, 0x73, 0x1a, 0x1f, 0x67,
0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74,
@@ -1122,7 +1183,7 @@ var file_agent_cvms_cvms_proto_rawDesc = []byte{
0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x74, 0x69,
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xc0, 0x02, 0x0a, 0x13, 0x43, 0x6c, 0x69, 0x65,
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x93, 0x03, 0x0a, 0x13, 0x43, 0x6c, 0x69, 0x65,
0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12,
0x2d, 0x0a, 0x09, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x63, 0x76, 0x6d, 0x73, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x4c,
@@ -1141,97 +1202,107 @@ var file_agent_cvms_cvms_proto_rawDesc = []byte{
0x65, 0x73, 0x12, 0x3b, 0x0a, 0x0d, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65,
0x52, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x76, 0x6d, 0x73,
0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x48, 0x00,
0x52, 0x0d, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x42,
0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x8d, 0x02, 0x0a, 0x13, 0x53,
0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61,
0x67, 0x65, 0x12, 0x38, 0x0a, 0x0c, 0x72, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x43, 0x68, 0x75, 0x6e,
0x6b, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x76, 0x6d, 0x73, 0x2e,
0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x48, 0x00, 0x52, 0x0c,
0x72, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x12, 0x31, 0x0a, 0x06,
0x72, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x63,
0x76, 0x6d, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
0x75, 0x6e, 0x52, 0x65, 0x71, 0x48, 0x00, 0x52, 0x06, 0x72, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x12,
0x41, 0x0a, 0x0f, 0x73, 0x74, 0x6f, 0x70, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x76, 0x6d, 0x73, 0x2e,
0x53, 0x74, 0x6f, 0x70, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x48,
0x00, 0x52, 0x0f, 0x73, 0x74, 0x6f, 0x70, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x0d, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65,
0x52, 0x65, 0x71, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x76, 0x6d, 0x73,
0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x48, 0x00,
0x52, 0x0d, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x42,
0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x4b, 0x0a, 0x0c, 0x52, 0x75,
0x6e, 0x52, 0x65, 0x71, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61,
0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x0e,
0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x17,
0x0a, 0x07, 0x69, 0x73, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52,
0x06, 0x69, 0x73, 0x4c, 0x61, 0x73, 0x74, 0x22, 0xaa, 0x02, 0x0a, 0x11, 0x43, 0x6f, 0x6d, 0x70,
0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x0e, 0x0a,
0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d,
0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x08, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x73, 0x18,
0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x63, 0x76, 0x6d, 0x73, 0x2e, 0x44, 0x61, 0x74,
0x61, 0x73, 0x65, 0x74, 0x52, 0x08, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x73, 0x12, 0x2d,
0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x76, 0x6d, 0x73, 0x2e, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74,
0x68, 0x6d, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x3f, 0x0a,
0x10, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72,
0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x76, 0x6d, 0x73, 0x2e, 0x52,
0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x52, 0x0f, 0x72,
0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x73, 0x12, 0x34,
0x0a, 0x0c, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x07,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x76, 0x6d, 0x73, 0x2e, 0x41, 0x67, 0x65, 0x6e,
0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x22, 0x2a, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x6f,
0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x4b, 0x65,
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x4b, 0x65, 0x79,
0x22, 0x53, 0x0a, 0x07, 0x44, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68,
0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12,
0x18, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c,
0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x69, 0x6c,
0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x69, 0x6c,
0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x39, 0x0a, 0x09, 0x41, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74,
0x68, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c,
0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x4b, 0x65,
0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x4b, 0x65, 0x79,
0x22, 0xf9, 0x01, 0x0a, 0x0b, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67,
0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x70, 0x6f, 0x72, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01,
0x28, 0x09, 0x52, 0x04, 0x68, 0x6f, 0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x65, 0x72, 0x74,
0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x65, 0x72,
0x74, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x69, 0x6c,
0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x46, 0x69, 0x6c, 0x65,
0x12, 0x24, 0x0a, 0x0e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x5f, 0x66, 0x69,
0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74,
0x43, 0x61, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72,
0x5f, 0x63, 0x61, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c,
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1b, 0x0a, 0x09,
0x6c, 0x6f, 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52,
0x08, 0x6c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x74, 0x74,
0x65, 0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x6c, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52,
0x0b, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x54, 0x6c, 0x73, 0x32, 0x50, 0x0a, 0x07,
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x45, 0x0a, 0x07, 0x50, 0x72, 0x6f, 0x63, 0x65,
0x73, 0x73, 0x12, 0x19, 0x2e, 0x63, 0x76, 0x6d, 0x73, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74,
0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x19, 0x2e,
0x63, 0x76, 0x6d, 0x73, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61,
0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x28, 0x01, 0x30, 0x01, 0x42, 0x08,
0x5a, 0x06, 0x2e, 0x2f, 0x63, 0x76, 0x6d, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
0x52, 0x0d, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x12,
0x51, 0x0a, 0x15, 0x76, 0x54, 0x50, 0x4d, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19,
0x2e, 0x63, 0x76, 0x6d, 0x73, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x48, 0x00, 0x52, 0x15, 0x76, 0x54, 0x50,
0x4d, 0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6f,
0x72, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x8d, 0x02,
0x0a, 0x13, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x38, 0x0a, 0x0c, 0x72, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x43,
0x68, 0x75, 0x6e, 0x6b, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x63, 0x76,
0x6d, 0x73, 0x2e, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x48,
0x00, 0x52, 0x0c, 0x72, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x12,
0x31, 0x0a, 0x06, 0x72, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x17, 0x2e, 0x63, 0x76, 0x6d, 0x73, 0x2e, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x48, 0x00, 0x52, 0x06, 0x72, 0x75, 0x6e, 0x52,
0x65, 0x71, 0x12, 0x41, 0x0a, 0x0f, 0x73, 0x74, 0x6f, 0x70, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x63, 0x76,
0x6d, 0x73, 0x2e, 0x53, 0x74, 0x6f, 0x70, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x48, 0x00, 0x52, 0x0f, 0x73, 0x74, 0x6f, 0x70, 0x43, 0x6f, 0x6d, 0x70, 0x75, 0x74,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3b, 0x0a, 0x0d, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x74,
0x61, 0x74, 0x65, 0x52, 0x65, 0x71, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63,
0x76, 0x6d, 0x73, 0x2e, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52, 0x65,
0x71, 0x48, 0x00, 0x52, 0x0d, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x52,
0x65, 0x71, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x4b, 0x0a,
0x0c, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71, 0x43, 0x68, 0x75, 0x6e, 0x6b, 0x73, 0x12, 0x12, 0x0a,
0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74,
0x61, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69,
0x64, 0x12, 0x17, 0x0a, 0x07, 0x69, 0x73, 0x5f, 0x6c, 0x61, 0x73, 0x74, 0x18, 0x03, 0x20, 0x01,
0x28, 0x08, 0x52, 0x06, 0x69, 0x73, 0x4c, 0x61, 0x73, 0x74, 0x22, 0xaa, 0x02, 0x0a, 0x11, 0x43,
0x6f, 0x6d, 0x70, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x75, 0x6e, 0x52, 0x65, 0x71,
0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64,
0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04,
0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72,
0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x29, 0x0a, 0x08, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65,
0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0d, 0x2e, 0x63, 0x76, 0x6d, 0x73, 0x2e,
0x44, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x52, 0x08, 0x64, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74,
0x73, 0x12, 0x2d, 0x0a, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d, 0x18, 0x05,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x0f, 0x2e, 0x63, 0x76, 0x6d, 0x73, 0x2e, 0x41, 0x6c, 0x67, 0x6f,
0x72, 0x69, 0x74, 0x68, 0x6d, 0x52, 0x09, 0x61, 0x6c, 0x67, 0x6f, 0x72, 0x69, 0x74, 0x68, 0x6d,
0x12, 0x3f, 0x0a, 0x10, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x75,
0x6d, 0x65, 0x72, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x63, 0x76, 0x6d,
0x73, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72,
0x52, 0x0f, 0x72, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72,
0x73, 0x12, 0x34, 0x0a, 0x0c, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69,
0x67, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x63, 0x76, 0x6d, 0x73, 0x2e, 0x41,
0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x0b, 0x61, 0x67, 0x65, 0x6e,
0x74, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x22, 0x2a, 0x0a, 0x0e, 0x52, 0x65, 0x73, 0x75, 0x6c,
0x74, 0x43, 0x6f, 0x6e, 0x73, 0x75, 0x6d, 0x65, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x73, 0x65,
0x72, 0x4b, 0x65, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72,
0x4b, 0x65, 0x79, 0x22, 0x53, 0x0a, 0x07, 0x44, 0x61, 0x74, 0x61, 0x73, 0x65, 0x74, 0x12, 0x12,
0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61,
0x73, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x73, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20,
0x01, 0x28, 0x0c, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x1a, 0x0a, 0x08,
0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
0x66, 0x69, 0x6c, 0x65, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x39, 0x0a, 0x09, 0x41, 0x6c, 0x67, 0x6f,
0x72, 0x69, 0x74, 0x68, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20,
0x01, 0x28, 0x0c, 0x52, 0x04, 0x68, 0x61, 0x73, 0x68, 0x12, 0x18, 0x0a, 0x07, 0x75, 0x73, 0x65,
0x72, 0x4b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72,
0x4b, 0x65, 0x79, 0x22, 0xe5, 0x01, 0x0a, 0x0b, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6e,
0x66, 0x69, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
0x09, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x65, 0x72, 0x74, 0x5f,
0x66, 0x69, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x65, 0x72, 0x74,
0x46, 0x69, 0x6c, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x6b, 0x65, 0x79, 0x5f, 0x66, 0x69, 0x6c, 0x65,
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6b, 0x65, 0x79, 0x46, 0x69, 0x6c, 0x65, 0x12,
0x24, 0x0a, 0x0e, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x63, 0x61, 0x5f, 0x66, 0x69, 0x6c,
0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x43,
0x61, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x5f,
0x63, 0x61, 0x5f, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73,
0x65, 0x72, 0x76, 0x65, 0x72, 0x43, 0x61, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6c,
0x6f, 0x67, 0x5f, 0x6c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08,
0x6c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x74, 0x74, 0x65,
0x73, 0x74, 0x65, 0x64, 0x5f, 0x74, 0x6c, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b,
0x61, 0x74, 0x74, 0x65, 0x73, 0x74, 0x65, 0x64, 0x54, 0x6c, 0x73, 0x22, 0x55, 0x0a, 0x13, 0x41,
0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c,
0x52, 0x04, 0x66, 0x69, 0x6c, 0x65, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x65, 0x72, 0x74, 0x53, 0x65,
0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
0x52, 0x10, 0x63, 0x65, 0x72, 0x74, 0x53, 0x65, 0x72, 0x69, 0x61, 0x6c, 0x4e, 0x75, 0x6d, 0x62,
0x65, 0x72, 0x32, 0x50, 0x0a, 0x07, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x45, 0x0a,
0x07, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x12, 0x19, 0x2e, 0x63, 0x76, 0x6d, 0x73, 0x2e,
0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x73, 0x73,
0x61, 0x67, 0x65, 0x1a, 0x19, 0x2e, 0x63, 0x76, 0x6d, 0x73, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x65,
0x72, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00,
0x28, 0x01, 0x30, 0x01, 0x42, 0x08, 0x5a, 0x06, 0x2e, 0x2f, 0x63, 0x76, 0x6d, 0x73, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
})
var (
file_agent_cvms_cvms_proto_rawDescOnce sync.Once
file_agent_cvms_cvms_proto_rawDescData = file_agent_cvms_cvms_proto_rawDesc
file_agent_cvms_cvms_proto_rawDescData []byte
)
func file_agent_cvms_cvms_proto_rawDescGZIP() []byte {
file_agent_cvms_cvms_proto_rawDescOnce.Do(func() {
file_agent_cvms_cvms_proto_rawDescData = protoimpl.X.CompressGZIP(file_agent_cvms_cvms_proto_rawDescData)
file_agent_cvms_cvms_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_agent_cvms_cvms_proto_rawDesc), len(file_agent_cvms_cvms_proto_rawDesc)))
})
return file_agent_cvms_cvms_proto_rawDescData
}
var file_agent_cvms_cvms_proto_msgTypes = make([]protoimpl.MessageInfo, 15)
var file_agent_cvms_cvms_proto_msgTypes = make([]protoimpl.MessageInfo, 16)
var file_agent_cvms_cvms_proto_goTypes = []any{
(*AgentStateReq)(nil), // 0: cvms.AgentStateReq
(*AgentStateRes)(nil), // 1: cvms.AgentStateRes
@@ -1248,31 +1319,33 @@ var file_agent_cvms_cvms_proto_goTypes = []any{
(*Dataset)(nil), // 12: cvms.Dataset
(*Algorithm)(nil), // 13: cvms.Algorithm
(*AgentConfig)(nil), // 14: cvms.AgentConfig
(*timestamppb.Timestamp)(nil), // 15: google.protobuf.Timestamp
(*AttestationResponse)(nil), // 15: cvms.AttestationResponse
(*timestamppb.Timestamp)(nil), // 16: google.protobuf.Timestamp
}
var file_agent_cvms_cvms_proto_depIdxs = []int32{
15, // 0: cvms.AgentEvent.timestamp:type_name -> google.protobuf.Timestamp
15, // 1: cvms.AgentLog.timestamp:type_name -> google.protobuf.Timestamp
16, // 0: cvms.AgentEvent.timestamp:type_name -> google.protobuf.Timestamp
16, // 1: cvms.AgentLog.timestamp:type_name -> google.protobuf.Timestamp
6, // 2: cvms.ClientStreamMessage.agent_log:type_name -> cvms.AgentLog
5, // 3: cvms.ClientStreamMessage.agent_event:type_name -> cvms.AgentEvent
4, // 4: cvms.ClientStreamMessage.run_res:type_name -> cvms.RunResponse
3, // 5: cvms.ClientStreamMessage.stopComputationRes:type_name -> cvms.StopComputationResponse
1, // 6: cvms.ClientStreamMessage.agentStateRes:type_name -> cvms.AgentStateRes
9, // 7: cvms.ServerStreamMessage.runReqChunks:type_name -> cvms.RunReqChunks
10, // 8: cvms.ServerStreamMessage.runReq:type_name -> cvms.ComputationRunReq
2, // 9: cvms.ServerStreamMessage.stopComputation:type_name -> cvms.StopComputation
0, // 10: cvms.ServerStreamMessage.agentStateReq:type_name -> cvms.AgentStateReq
12, // 11: cvms.ComputationRunReq.datasets:type_name -> cvms.Dataset
13, // 12: cvms.ComputationRunReq.algorithm:type_name -> cvms.Algorithm
11, // 13: cvms.ComputationRunReq.result_consumers:type_name -> cvms.ResultConsumer
14, // 14: cvms.ComputationRunReq.agent_config:type_name -> cvms.AgentConfig
7, // 15: cvms.Service.Process:input_type -> cvms.ClientStreamMessage
8, // 16: cvms.Service.Process:output_type -> cvms.ServerStreamMessage
16, // [16:17] is the sub-list for method output_type
15, // [15:16] is the sub-list for method input_type
15, // [15:15] is the sub-list for extension type_name
15, // [15:15] is the sub-list for extension extendee
0, // [0:15] is the sub-list for field type_name
15, // 7: cvms.ClientStreamMessage.vTPMattestationReport:type_name -> cvms.AttestationResponse
9, // 8: cvms.ServerStreamMessage.runReqChunks:type_name -> cvms.RunReqChunks
10, // 9: cvms.ServerStreamMessage.runReq:type_name -> cvms.ComputationRunReq
2, // 10: cvms.ServerStreamMessage.stopComputation:type_name -> cvms.StopComputation
0, // 11: cvms.ServerStreamMessage.agentStateReq:type_name -> cvms.AgentStateReq
12, // 12: cvms.ComputationRunReq.datasets:type_name -> cvms.Dataset
13, // 13: cvms.ComputationRunReq.algorithm:type_name -> cvms.Algorithm
11, // 14: cvms.ComputationRunReq.result_consumers:type_name -> cvms.ResultConsumer
14, // 15: cvms.ComputationRunReq.agent_config:type_name -> cvms.AgentConfig
7, // 16: cvms.Service.Process:input_type -> cvms.ClientStreamMessage
8, // 17: cvms.Service.Process:output_type -> cvms.ServerStreamMessage
17, // [17:18] is the sub-list for method output_type
16, // [16:17] is the sub-list for method input_type
16, // [16:16] is the sub-list for extension type_name
16, // [16:16] is the sub-list for extension extendee
0, // [0:16] is the sub-list for field type_name
}
func init() { file_agent_cvms_cvms_proto_init() }
@@ -1286,6 +1359,7 @@ func file_agent_cvms_cvms_proto_init() {
(*ClientStreamMessage_RunRes)(nil),
(*ClientStreamMessage_StopComputationRes)(nil),
(*ClientStreamMessage_AgentStateRes)(nil),
(*ClientStreamMessage_VTPMattestationReport)(nil),
}
file_agent_cvms_cvms_proto_msgTypes[8].OneofWrappers = []any{
(*ServerStreamMessage_RunReqChunks)(nil),
@@ -1297,9 +1371,9 @@ func file_agent_cvms_cvms_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_agent_cvms_cvms_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_agent_cvms_cvms_proto_rawDesc), len(file_agent_cvms_cvms_proto_rawDesc)),
NumEnums: 0,
NumMessages: 15,
NumMessages: 16,
NumExtensions: 0,
NumServices: 1,
},
@@ -1308,7 +1382,6 @@ func file_agent_cvms_cvms_proto_init() {
MessageInfos: file_agent_cvms_cvms_proto_msgTypes,
}.Build()
File_agent_cvms_cvms_proto = out.File
file_agent_cvms_cvms_proto_rawDesc = nil
file_agent_cvms_cvms_proto_goTypes = nil
file_agent_cvms_cvms_proto_depIdxs = nil
}
+12 -7
View File
@@ -59,6 +59,7 @@ message ClientStreamMessage {
RunResponse run_res = 3;
StopComputationResponse stopComputationRes = 4;
AgentStateRes agentStateRes = 5;
AttestationResponse vTPMattestationReport = 6;
}
}
@@ -104,11 +105,15 @@ message Algorithm {
message AgentConfig {
string port = 1;
string host = 2;
string cert_file = 3;
string key_file = 4;
string client_ca_file = 5;
string server_ca_file = 6;
string log_level = 7;
bool attested_tls = 8;
string cert_file = 2;
string key_file = 3;
string client_ca_file = 4;
string server_ca_file = 5;
string log_level = 6;
bool attested_tls = 7;
}
message AttestationResponse {
bytes file = 1;
string certSerialNumber = 2;
}
+4 -2
View File
@@ -32,12 +32,14 @@ type agentServer struct {
gs server.Server
logger *slog.Logger
svc agent.Service
host string
}
func NewServer(logger *slog.Logger, svc agent.Service) AgentServer {
func NewServer(logger *slog.Logger, svc agent.Service, host string) AgentServer {
return &agentServer{
logger: logger,
svc: svc,
host: host,
}
}
@@ -49,7 +51,7 @@ func (as *agentServer) Start(cfg agent.AgentConfig, cmp agent.Computation) error
agentGrpcServerConfig := server.AgentConfig{
ServerConfig: server.ServerConfig{
BaseConfig: server.BaseConfig{
Host: cfg.Host,
Host: as.host,
Port: cfg.Port,
CertFile: cfg.CertFile,
KeyFile: cfg.KeyFile,
+7 -7
View File
@@ -3,7 +3,7 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.0
// protoc-gen-go v1.36.5
// protoc v5.29.0
// source: agent/events/events.proto
@@ -15,6 +15,7 @@ import (
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
@@ -260,7 +261,7 @@ func (*EventsLogs_AgentEvent) isEventsLogs_Message() {}
var File_agent_events_events_proto protoreflect.FileDescriptor
var file_agent_events_events_proto_rawDesc = []byte{
var file_agent_events_events_proto_rawDesc = string([]byte{
0x0a, 0x19, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2f, 0x65,
0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, 0x65, 0x76, 0x65,
0x6e, 0x74, 0x73, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74,
@@ -299,16 +300,16 @@ var file_agent_events_events_proto_rawDesc = []byte{
0x67, 0x65, 0x6e, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73,
0x73, 0x61, 0x67, 0x65, 0x42, 0x0a, 0x5a, 0x08, 0x2e, 0x2f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
})
var (
file_agent_events_events_proto_rawDescOnce sync.Once
file_agent_events_events_proto_rawDescData = file_agent_events_events_proto_rawDesc
file_agent_events_events_proto_rawDescData []byte
)
func file_agent_events_events_proto_rawDescGZIP() []byte {
file_agent_events_events_proto_rawDescOnce.Do(func() {
file_agent_events_events_proto_rawDescData = protoimpl.X.CompressGZIP(file_agent_events_events_proto_rawDescData)
file_agent_events_events_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_agent_events_events_proto_rawDesc), len(file_agent_events_events_proto_rawDesc)))
})
return file_agent_events_events_proto_rawDescData
}
@@ -345,7 +346,7 @@ func file_agent_events_events_proto_init() {
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_agent_events_events_proto_rawDesc,
RawDescriptor: unsafe.Slice(unsafe.StringData(file_agent_events_events_proto_rawDesc), len(file_agent_events_events_proto_rawDesc)),
NumEnums: 0,
NumMessages: 3,
NumExtensions: 0,
@@ -356,7 +357,6 @@ func file_agent_events_events_proto_init() {
MessageInfos: file_agent_events_events_proto_msgTypes,
}.Build()
File_agent_events_events_proto = out.File
file_agent_events_events_proto_rawDesc = nil
file_agent_events_events_proto_goTypes = nil
file_agent_events_events_proto_depIdxs = nil
}
+17 -1
View File
@@ -639,7 +639,23 @@ func (cli *CLI) NewMeasureCmd(igvmBinaryPath string) *cobra.Command {
inputFile := args[0]
return cli.measurement.Run(inputFile)
measurement, err := cli.measurement.Run(inputFile)
if err != nil {
return err
}
outputString := string(measurement)
lines := strings.Split(strings.TrimSpace(outputString), "\n")
if len(lines) == 1 {
outputString = strings.ToLower(outputString)
} else {
return fmt.Errorf("error: %s", outputString)
}
cmd.Print(outputString)
return nil
},
}
+138 -7
View File
@@ -3,15 +3,22 @@
package cli
import (
"bytes"
"crypto/sha512"
"encoding/base64"
"encoding/json"
"fmt"
"os"
"strconv"
"github.com/absmach/magistrala/pkg/errors"
"github.com/google/go-sev-guest/proto/check"
"github.com/google/go-tpm-tools/proto/attest"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"google.golang.org/protobuf/encoding/protojson"
config "github.com/ultravioletrs/cocos/pkg/attestation"
"github.com/ultravioletrs/cocos/pkg/attestation/gcp"
"google.golang.org/protobuf/proto"
)
type fieldType int
@@ -99,6 +106,126 @@ func (cli *CLI) NewAddHostDataCmd() *cobra.Command {
}
}
func (cli *CLI) NewGCPAttestationPolicy() *cobra.Command {
return &cobra.Command{
Use: "gcp",
Short: "Get attestation policy for GCP CVM",
Example: `gcp <bin_vtmp_attestation_report_file> <vcpu_count>`,
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
attestationBin, err := os.ReadFile(args[0])
if err != nil {
printError(cmd, "Error reading attestation report file: %v ❌ ", err)
return
}
vcpuCount, err := strconv.Atoi(args[1])
if err != nil {
printError(cmd, "Error converting vCPU count to integer: %v ❌ ", err)
return
}
attestation := &attest.Attestation{}
if err := proto.Unmarshal(attestationBin, attestation); err != nil {
printError(cmd, "Error unmarshaling attestation report: %v ❌ ", err)
return
}
attestationPB := attestation.GetSevSnpAttestation()
measurement, err := gcp.Extract384BitMeasurement(attestationPB)
if err != nil {
printError(cmd, "Error extracting 384-bit measurement: %v ❌ ", err)
return
}
launchEndorsement, err := gcp.GetLaunchEndorsement(cmd.Context(), measurement)
if err != nil {
printError(cmd, "Error getting launch endorsement: %v ❌ ", err)
return
}
attestationPolicy, err := gcp.GenerateAttestationPolicy(launchEndorsement, uint32(vcpuCount))
if err != nil {
printError(cmd, "Error generating attestation policy: %v ❌ ", err)
return
}
attestationPolicyJson, err := json.MarshalIndent(attestationPolicy, "", " ")
if err != nil {
printError(cmd, "Error marshaling attestation policy: %v ❌ ", err)
return
}
if err := os.WriteFile("attestation_policy.json", attestationPolicyJson, filePermission); err != nil {
printError(cmd, "Error writing attestation policy file: %v ❌ ", err)
return
}
cmd.Println("Attestation policy file generated successfully ✅")
},
}
}
func (cli *CLI) NewDownloadGCPOvmfFile() *cobra.Command {
return &cobra.Command{
Use: "download",
Short: "Download GCP OVMF file",
Example: `download <bin_vtmp_attestation_report_file>`,
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
attestationBin, err := os.ReadFile(args[0])
if err != nil {
printError(cmd, "Error reading attestation report file: %v ❌ ", err)
return
}
attestation := &attest.Attestation{}
if err := proto.Unmarshal(attestationBin, attestation); err != nil {
printError(cmd, "Error unmarshaling attestation report: %v ❌ ", err)
return
}
attestationPB := attestation.GetSevSnpAttestation()
measurement, err := gcp.Extract384BitMeasurement(attestationPB)
if err != nil {
printError(cmd, "Error extracting 384-bit measurement: %v ❌ ", err)
return
}
launchEndorsement, err := gcp.GetLaunchEndorsement(cmd.Context(), measurement)
if err != nil {
printError(cmd, "Error getting launch endorsement: %v ❌ ", err)
return
}
ovmf, err := gcp.DownloadOvmfFile(cmd.Context(), fmt.Sprintf("%x", launchEndorsement.Digest))
if err != nil {
printError(cmd, "Error downloading OVMF file: %v ❌ ", err)
return
}
sum384 := sha512.Sum384(ovmf)
if !bytes.Equal(sum384[:], launchEndorsement.Digest) {
printError(cmd, "Error OVMF file does not match the measurement: %v ❌ ", fmt.Errorf("digest mismatch"))
} else {
cmd.Println("OVMF firmware in vm is unmodified ✅")
}
if err := os.WriteFile("ovmf.fd", ovmf, filePermission); err != nil {
printError(cmd, "Error writing OVMF file: %v ❌ ", err)
return
}
cmd.Println("OVMF file downloaded successfully ✅")
},
}
}
func changeAttestationConfiguration(fileName, base64Data string, expectedLength int, field fieldType) error {
data, err := base64.StdEncoding.DecodeString(base64Data)
if err != nil {
@@ -109,27 +236,31 @@ func changeAttestationConfiguration(fileName, base64Data string, expectedLength
return errDataLength
}
ac := check.Config{Policy: &check.Policy{}, RootOfTrust: &check.RootOfTrust{}}
ac := config.Config{Config: &check.Config{RootOfTrust: &check.RootOfTrust{}, Policy: &check.Policy{}}, PcrConfig: &config.PcrConfig{}}
attestationPolicy, err := os.ReadFile(fileName)
f, err := os.ReadFile(fileName)
if err != nil {
return errors.Wrap(errReadingAttestationPolicyFile, err)
}
if err = protojson.Unmarshal(attestationPolicy, &ac); err != nil {
if err = config.ReadAttestationPolicyFromByte(f, &ac); err != nil {
return errors.Wrap(errUnmarshalJSON, err)
}
if ac.Config.Policy == nil {
ac.Config.Policy = &check.Policy{}
}
switch field {
case measurementField:
ac.Policy.Measurement = data
ac.Config.Policy.Measurement = data
case hostDataField:
ac.Policy.HostData = data
ac.Config.Policy.HostData = data
default:
return errAttestationPolicyField
}
fileJson, err := protojson.Marshal(&ac)
fileJson, err := json.MarshalIndent(&ac, "", " ")
if err != nil {
return errors.Wrap(errMarshalJSON, err)
}
+8 -7
View File
@@ -4,13 +4,14 @@ package cli
import (
"encoding/base64"
"encoding/json"
"os"
"testing"
"github.com/google/go-sev-guest/proto/check"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"google.golang.org/protobuf/encoding/protojson"
config "github.com/ultravioletrs/cocos/pkg/attestation"
)
func TestChangeAttestationConfiguration(t *testing.T) {
@@ -18,9 +19,9 @@ func TestChangeAttestationConfiguration(t *testing.T) {
require.NoError(t, err)
defer os.Remove(tmpfile.Name())
initialConfig := check.Config{Policy: &check.Policy{}, RootOfTrust: &check.RootOfTrust{}}
initialConfig := config.Config{Config: &check.Config{RootOfTrust: &check.RootOfTrust{}, Policy: &check.Policy{}}, PcrConfig: &config.PcrConfig{}}
initialJSON, err := protojson.Marshal(&initialConfig)
initialJSON, err := json.Marshal(initialConfig)
require.NoError(t, err)
err = os.WriteFile(tmpfile.Name(), initialJSON, 0o644)
require.NoError(t, err)
@@ -86,15 +87,15 @@ func TestChangeAttestationConfiguration(t *testing.T) {
content, err := os.ReadFile(tmpfile.Name())
require.NoError(t, err)
config := check.Config{Policy: &check.Policy{}, RootOfTrust: &check.RootOfTrust{}}
err = protojson.Unmarshal(content, &config)
ap := config.Config{Config: &check.Config{RootOfTrust: &check.RootOfTrust{}, Policy: &check.Policy{}}, PcrConfig: &config.PcrConfig{}}
err = config.ReadAttestationPolicyFromByte(content, &ap)
require.NoError(t, err)
decodedData, _ := base64.StdEncoding.DecodeString(tt.base64Data)
if tt.field == measurementField {
assert.Equal(t, decodedData, config.Policy.Measurement)
assert.Equal(t, decodedData, ap.Config.Policy.Measurement)
} else if tt.field == hostDataField {
assert.Equal(t, decodedData, config.Policy.HostData)
assert.Equal(t, decodedData, ap.Config.Policy.HostData)
}
}
})
+2 -2
View File
@@ -287,9 +287,9 @@ type MockMeasurement struct {
mock.Mock
}
func (m *MockMeasurement) Run(igvmBinaryPath string) error {
func (m *MockMeasurement) Run(igvmBinaryPath string) ([]byte, error) {
args := m.Called(igvmBinaryPath)
return args.Error(0)
return nil, args.Error(0)
}
func (m *MockMeasurement) Stop() error {
+2 -2
View File
@@ -27,14 +27,14 @@ func (cli *CLI) NewCABundleCmd(fileSavePath string) *cobra.Command {
Example: "ca-bundle <path_to_platform_info_json>",
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
attestationConfiguration := config.Config{SnpCheck: &check.Config{Policy: &check.Policy{}, RootOfTrust: &check.RootOfTrust{}}, PcrConfig: &config.PcrConfig{}}
attestationConfiguration := config.Config{Config: &check.Config{Policy: &check.Policy{}, RootOfTrust: &check.RootOfTrust{}}, PcrConfig: &config.PcrConfig{}}
err := config.ReadAttestationPolicy(args[0], &attestationConfiguration)
if err != nil {
printError(cmd, "Error while reading manifest: %v ❌ ", err)
return
}
product := attestationConfiguration.SnpCheck.RootOfTrust.ProductLine
product := attestationConfiguration.Config.RootOfTrust.ProductLine
getter := trust.DefaultHTTPSGetter()
caURL := kds.ProductCertChainURL(abi.VcekReportSigner, product)
+3 -3
View File
@@ -7,7 +7,7 @@ import (
"github.com/spf13/cobra"
"github.com/ultravioletrs/cocos/manager"
"github.com/ultravioletrs/cocos/pkg/attestation/igvmmeasure"
"github.com/ultravioletrs/cocos/pkg/attestation/cmdconfig"
"github.com/ultravioletrs/cocos/pkg/clients/grpc"
"github.com/ultravioletrs/cocos/pkg/clients/grpc/agent"
managergrpc "github.com/ultravioletrs/cocos/pkg/clients/grpc/manager"
@@ -23,10 +23,10 @@ type CLI struct {
client grpc.Client
managerClient manager.ManagerServiceClient
connectErr error
measurement igvmmeasure.MeasurementProvider
measurement cmdconfig.MeasurementProvider
}
func New(agentConfig grpc.AgentClientConfig, managerConfig grpc.ManagerClientConfig, measurement igvmmeasure.MeasurementProvider) *CLI {
func New(agentConfig grpc.AgentClientConfig, managerConfig grpc.ManagerClientConfig, measurement cmdconfig.MeasurementProvider) *CLI {
return &CLI{
agentConfig: agentConfig,
managerConfig: managerConfig,
+51 -3
View File
@@ -4,6 +4,10 @@ package main
import (
"context"
"crypto/sha256"
"crypto/sha512"
"crypto/x509"
"encoding/pem"
"errors"
"fmt"
"log"
@@ -25,6 +29,7 @@ import (
"github.com/ultravioletrs/cocos/agent/cvms/server"
"github.com/ultravioletrs/cocos/agent/events"
agentlogger "github.com/ultravioletrs/cocos/internal/logger"
attestationconfig "github.com/ultravioletrs/cocos/pkg/attestation"
"github.com/ultravioletrs/cocos/pkg/attestation/quoteprovider"
"github.com/ultravioletrs/cocos/pkg/attestation/quoteprovider/mocks"
pkggrpc "github.com/ultravioletrs/cocos/pkg/clients/grpc"
@@ -41,8 +46,9 @@ const (
)
type config struct {
LogLevel string `env:"AGENT_LOG_LEVEL" envDefault:"debug"`
Vmpl int `env:"AGENT_VMPL" envDefault:"2"`
LogLevel string `env:"AGENT_LOG_LEVEL" envDefault:"debug"`
Vmpl int `env:"AGENT_VMPL" envDefault:"2"`
AgentGrpcHost string `env:"AGENT_GRPC_HOST" envDefault:"0.0.0.0"`
}
func main() {
@@ -138,7 +144,7 @@ func main() {
return
}
mc, err := cvmsapi.NewClient(pc, svc, eventsLogsQueue, logger, server.NewServer(logger, svc), storageDir, reconnectFn)
mc, err := cvmsapi.NewClient(pc, svc, eventsLogsQueue, logger, server.NewServer(logger, svc, cfg.AgentGrpcHost), storageDir, reconnectFn)
if err != nil {
logger.Error(err.Error())
exitCode = 1
@@ -164,6 +170,22 @@ func main() {
return mc.Process(ctx, cancel)
})
attestation, certSerialNumber, err := attestationFromCert(ctx, cvmGrpcConfig.ClientCert, svc)
if err != nil {
logger.Error(fmt.Sprintf("failed to get attestation: %s", err))
exitCode = 1
return
}
eventsLogsQueue <- &cvms.ClientStreamMessage{
Message: &cvms.ClientStreamMessage_VTPMattestationReport{
VTPMattestationReport: &cvms.AttestationResponse{
File: attestation,
CertSerialNumber: certSerialNumber,
},
},
}
if err := g.Wait(); err != nil {
logger.Error(fmt.Sprintf("%s service terminated: %s", svcName, err))
}
@@ -187,3 +209,29 @@ func sevGuesDeviceExists() bool {
d.Close()
return true
}
func attestationFromCert(ctx context.Context, certFilePath string, svc agent.Service) ([]byte, string, error) {
if certFilePath == "" {
return nil, "", nil
}
certFile, err := os.ReadFile(certFilePath)
if err != nil {
return nil, "", err
}
certPem, _ := pem.Decode(certFile)
certx509, err := x509.ParseCertificate(certPem.Bytes)
if err != nil {
return nil, "", err
}
nonceSNP := sha512.Sum512(certFile)
nonceVTPM := sha256.Sum256(certFile)
attestation, err := svc.Attestation(ctx, nonceSNP, nonceVTPM, attestationconfig.SNPvTPM)
if err != nil {
return nil, "", err
}
return attestation, certx509.SerialNumber.String(), nil
}
+5 -2
View File
@@ -14,7 +14,7 @@ import (
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"github.com/ultravioletrs/cocos/cli"
"github.com/ultravioletrs/cocos/pkg/attestation/igvmmeasure"
"github.com/ultravioletrs/cocos/pkg/attestation/cmdconfig"
"github.com/ultravioletrs/cocos/pkg/clients/grpc"
cmd "github.com/virtee/sev-snp-measure-go/sevsnpmeasure/cmd"
)
@@ -108,7 +108,8 @@ func main() {
return
}
measurement, err := igvmmeasure.NewIgvmMeasurement(cfg.IgvmBinaryPath, os.Stderr, os.Stdout)
options := cmdconfig.IgvmMeasureOptions
measurement, err := cmdconfig.NewCmdConfig(cfg.IgvmBinaryPath, options, os.Stderr)
if err != nil {
message := color.New(color.FgRed).Sprintf("failed to initialize measurement: %s", err) // Use %s instead of %w
rootCmd.Println(message)
@@ -159,6 +160,8 @@ func main() {
// Attestation Policy commands
attestationPolicyCmd.AddCommand(cliSVC.NewAddMeasurementCmd())
attestationPolicyCmd.AddCommand(cliSVC.NewAddHostDataCmd())
attestationPolicyCmd.AddCommand(cliSVC.NewGCPAttestationPolicy())
attestationPolicyCmd.AddCommand(cliSVC.NewDownloadGCPOvmfFile())
if err := rootCmd.Execute(); err != nil {
logErrorCmd(*rootCmd, err)
+6 -4
View File
@@ -42,7 +42,9 @@ type config struct {
JaegerURL url.URL `env:"COCOS_JAEGER_URL" envDefault:"http://localhost:4318"`
TraceRatio float64 `env:"COCOS_JAEGER_TRACE_RATIO" envDefault:"1.0"`
InstanceID string `env:"MANAGER_INSTANCE_ID" envDefault:""`
AttestationPolicyBinary string `env:"MANAGER_ATTESTATION_POLICY_BINARY" envDefault:"../../build"`
AttestationPolicyBinary string `env:"MANAGER_ATTESTATION_POLICY_BINARY" envDefault:"../../build/attestation_policy"`
IgvmMeasureBinary string `env:"MANAGER_IGVMMEASURE_BINARY" envDefault:"../../build/igvmmeasure"`
PcrValues string `env:"MANAGER_PCR_VALUES" envDefault:""`
EosVersion string `env:"MANAGER_EOS_VERSION" envDefault:""`
}
@@ -98,7 +100,7 @@ func main() {
return
}
svc, err := newService(logger, tracer, qemuCfg, cfg.AttestationPolicyBinary, cfg.EosVersion)
svc, err := newService(logger, tracer, qemuCfg, cfg.AttestationPolicyBinary, cfg.IgvmMeasureBinary, cfg.PcrValues, cfg.EosVersion)
if err != nil {
logger.Error(err.Error())
exitCode = 1
@@ -125,8 +127,8 @@ func main() {
}
}
func newService(logger *slog.Logger, tracer trace.Tracer, qemuCfg qemu.Config, attestationPolicyPath string, eosVersion string) (manager.Service, error) {
svc, err := manager.New(qemuCfg, attestationPolicyPath, logger, qemu.NewVM, eosVersion)
func newService(logger *slog.Logger, tracer trace.Tracer, qemuCfg qemu.Config, attestationPolicyPath string, igvmMeasurementBinaryPath string, pcrValuesFilePath string, eosVersion string) (manager.Service, error) {
svc, err := manager.New(qemuCfg, attestationPolicyPath, igvmMeasurementBinaryPath, pcrValuesFilePath, logger, qemu.NewVM, eosVersion)
if err != nil {
return nil, err
}
+2
View File
@@ -7,6 +7,8 @@ COCOS_JAEGER_TRACE_RATIO=1.0
# Manager Service Configuration
MANAGER_INSTANCE_ID=
MANAGER_ATTESTATION_POLICY_BINARY=../../build
MANAGER_IGVMMEASURE_BINARY=../../build
MANAGER_PCR_VALUES=/etc/cocos/pcr_values.json
MANAGER_GRPC_CLIENT_CERT=
MANAGER_GRPC_CLIENT_KEY=
MANAGER_GRPC_SERVER_CA_CERTS=
+33 -9
View File
@@ -8,7 +8,7 @@ require (
github.com/fatih/color v1.18.0
github.com/go-kit/kit v0.13.0
github.com/gofrs/uuid v4.4.0+incompatible
github.com/google/go-sev-guest v0.12.1
github.com/google/go-sev-guest v0.13.0
github.com/google/go-tdx-guest v0.3.2-0.20241009005452-097ee70d0843 // indirect
github.com/mdlayher/vsock v1.2.1
github.com/spf13/cobra v1.9.1
@@ -18,27 +18,44 @@ require (
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0
go.opentelemetry.io/otel/trace v1.34.0
golang.org/x/crypto v0.35.0
golang.org/x/sync v0.11.0
google.golang.org/grpc v1.70.0
golang.org/x/sync v0.12.0
google.golang.org/grpc v1.71.0
google.golang.org/protobuf v1.36.5
)
require (
cel.dev/expr v0.19.2 // indirect
cloud.google.com/go v0.118.3 // indirect
cloud.google.com/go/auth v0.15.0 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.7 // indirect
cloud.google.com/go/compute/metadata v0.6.0 // indirect
cloud.google.com/go/iam v1.4.1 // indirect
cloud.google.com/go/monitoring v1.24.0 // indirect
cloud.google.com/go/storage v1.51.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 // indirect
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0 // indirect
github.com/Microsoft/go-winio v0.6.2 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 // indirect
github.com/containerd/log v0.1.0 // indirect
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/gofrs/uuid/v5 v5.3.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/certificate-transparency-go v1.1.2 // indirect
github.com/google/gce-tcb-verifier v0.2.3-0.20240905212129-12f728a62786 // indirect
github.com/google/gce-tcb-verifier v0.3.1 // indirect
github.com/google/go-attestation v0.5.1 // indirect
github.com/google/go-eventlog v0.0.2-0.20241003021507-01bb555f7cba // indirect
github.com/google/go-tspi v0.3.0 // indirect
github.com/google/s2a-go v0.1.9 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.5 // indirect
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
@@ -46,13 +63,20 @@ require (
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.1.0 // indirect
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0 // indirect
go.opentelemetry.io/contrib/detectors/gcp v1.34.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 // indirect
go.opentelemetry.io/otel v1.34.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.32.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.32.0 // indirect
go.opentelemetry.io/otel/sdk v1.32.0 // indirect
go.opentelemetry.io/otel/sdk v1.34.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect
golang.org/x/exp v0.0.0-20240909161429-701f63a606c0 // indirect
golang.org/x/oauth2 v0.28.0 // indirect
golang.org/x/time v0.10.0 // indirect
google.golang.org/api v0.224.0 // indirect
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb // indirect
gotest.tools/v3 v3.5.1 // indirect
)
@@ -83,12 +107,12 @@ require (
go.opentelemetry.io/otel/metric v1.34.0 // indirect
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/net v0.34.0 // indirect
golang.org/x/net v0.35.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/term v0.29.0
golang.org/x/text v0.22.0 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
+70
View File
@@ -1,5 +1,7 @@
bazil.org/fuse v0.0.0-20180421153158-65cc252bf669/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8=
bitbucket.org/creachadair/shell v0.0.6/go.mod h1:8Qqi/cYk7vPnsOePHroKXDJYmb5x7ENhtiFtfZq8K+M=
cel.dev/expr v0.19.2 h1:V354PbqIXr9IQdwy4SYA4xa0HXaWq1BUPAGzugBY5V4=
cel.dev/expr v0.19.2/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
@@ -30,16 +32,28 @@ cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aD
cloud.google.com/go v0.92.2/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
cloud.google.com/go v0.92.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
cloud.google.com/go v0.118.3 h1:jsypSnrE/w4mJysioGdMBg4MiW/hHx/sArFpaBWHdME=
cloud.google.com/go v0.118.3/go.mod h1:Lhs3YLnBlwJ4KA6nuObNMZ/fCbOQBPuWKPoE0Wa/9Vc=
cloud.google.com/go/auth v0.15.0 h1:Ly0u4aA5vG/fsSsxu98qCQBemXtAtJf+95z9HK+cxps=
cloud.google.com/go/auth v0.15.0/go.mod h1:WJDGqZ1o9E9wKIL+IwStfyn/+s59zl4Bi+1KQNVXLZ8=
cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74z6cBk9Rw6M=
cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/iam v1.4.1 h1:cFC25Nv+u5BkTR/BT1tXdoF2daiVbZ1RLx2eqfQ9RMM=
cloud.google.com/go/iam v1.4.1/go.mod h1:2vUEJpUG3Q9p2UdsyksaKpDzlwOrnMzS30isdReIcLM=
cloud.google.com/go/monitoring v0.1.0/go.mod h1:Hpm3XfzJv+UTiXzCG5Ffp0wijzHTC7Cv4eR7o3x/fEE=
cloud.google.com/go/monitoring v1.24.0 h1:csSKiCJ+WVRgNkRzzz3BPoGjFhjPY23ZTcaenToJxMM=
cloud.google.com/go/monitoring v1.24.0/go.mod h1:Bd1PRK5bmQBQNnuGwHBfUamAV1ys9049oEPHnn4pcsc=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
@@ -52,6 +66,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
cloud.google.com/go/storage v1.51.0 h1:ZVZ11zCiD7b3k+cH5lQs/qcNaoSz3U9I0jgwVzqDlCw=
cloud.google.com/go/storage v1.51.0/go.mod h1:YEJfu/Ki3i5oHC/7jyTgsGZwdQ8P9hqMqvpi5kRKGgc=
cloud.google.com/go/trace v0.1.0/go.mod h1:wxEwsoeRVPbeSkt7ZC9nWCgmoKQRAoySN7XHW2AmI7g=
code.gitea.io/sdk/gitea v0.11.3/go.mod h1:z3uwDV/b9Ls47NGukYM9XhnHtqPh/J+t40lsUrR6JDY=
contrib.go.opencensus.io/exporter/aws v0.0.0-20181029163544-2befc13012d0/go.mod h1:uu1P0UCM/6RbsMrgPa98ll8ZcHM858i/AD06a9aLRCA=
@@ -74,6 +90,12 @@ github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSW
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 h1:fYE9p3esPxA/C0rQ0AHhP0drtPXDRhaWiwg1DPqO7IU=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0/go.mod h1:BnBReJLvVYx2CS/UHOgVz2BXKXD9wsQPxZug20nZhd0=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0 h1:6/0iUd0xrnX7qt+mLNRwg5c0PGv8wpE8K90ryANQwMI=
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0/go.mod h1:otE2jQekW/PqXk1Awf5lmfokJx4uwuqcj1ab5SpGeW0=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
github.com/Masterminds/semver v1.4.2/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
@@ -162,6 +184,8 @@ github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGX
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42 h1:Om6kYQYDUk5wWbT0t0q6pvyM49i9XZAv9dDrkDA7gjk=
github.com/cncf/xds/go v0.0.0-20250121191232-2f005788dc42/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/cockroachdb/datadriven v0.0.0-20200714090401-bf6692d28da5/go.mod h1:h6jFvWxBdQXxjopDMZyH2UVceIRfR84bdzbkoKrsWNo=
github.com/cockroachdb/errors v1.2.4/go.mod h1:rQD95gz6FARkaKkQXUksEje/d9a6wBJoCr5oaCLELYA=
@@ -222,8 +246,13 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M=
github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A=
github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v0.3.0-java/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8=
github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU=
github.com/etcd-io/gofail v0.0.0-20190801230047-ad7f989257ca/go.mod h1:49H/RkXP8pKaZy4h0d+NW16rSLhyVBt4o6VLJbmOqDE=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
@@ -337,6 +366,8 @@ github.com/google/certificate-transparency-go v1.1.2 h1:4hE0GEId6NAW28dFpC+LrRGw
github.com/google/certificate-transparency-go v1.1.2/go.mod h1:3OL+HKDqHPUfdKrHVQxO6T8nDLO0HF7LRTlkIWXaWvQ=
github.com/google/gce-tcb-verifier v0.2.3-0.20240905212129-12f728a62786 h1:1ijRI0+jsZCl3CqeJG3Cib6w+wYCBlD/rWRo5a+ZME4=
github.com/google/gce-tcb-verifier v0.2.3-0.20240905212129-12f728a62786/go.mod h1:Jvv9i6JF1t7sDVW09zP2x+9vN3lcujtih2Zb/lVXaLs=
github.com/google/gce-tcb-verifier v0.3.1 h1:4L9YgkOtqC2U7cj4FofCUufHFCCpdD4Y0yPKI8UhOhI=
github.com/google/gce-tcb-verifier v0.3.1/go.mod h1:GZCDLQxmEOCqUTL2BMB/zjo+hgXdUrR0Wgwz1OrwRYg=
github.com/google/go-attestation v0.5.1 h1:jqtOrLk5MNdliTKjPbIPrAaRKJaKW+0LIU2n/brJYms=
github.com/google/go-attestation v0.5.1/go.mod h1:KqGatdUhg5kPFkokyzSBDxwSCFyRgIgtRkMp6c3lOBQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
@@ -353,6 +384,7 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-configfs-tsm v0.3.3-0.20240919001351-b4b5b84fdcbc h1:SG12DWUUM5igxm+//YX5Yq4vhdoRnOG9HkCodkOn+YU=
github.com/google/go-configfs-tsm v0.3.3-0.20240919001351-b4b5b84fdcbc/go.mod h1:EL1GTDFMb5PZQWDviGfZV9n87WeGTR/JUg13RfwkgRo=
github.com/google/go-eventlog v0.0.2-0.20241003021507-01bb555f7cba h1:05m5+kgZjxYUZrx3bZfkKHl6wkch+Khao6N21rFHInk=
@@ -364,6 +396,8 @@ github.com/google/go-replayers/grpcreplay v0.1.0/go.mod h1:8Ig2Idjpr6gifRd6pNVgg
github.com/google/go-replayers/httpreplay v0.1.0/go.mod h1:YKZViNhiGgqdBlUbI2MwGpq4pXxNmhJLPHQ7cv2b5no=
github.com/google/go-sev-guest v0.12.1 h1:H4rFYnPIn8HtqEsNTmh56Zxcf9BI9n48ZSYCnpYLYvc=
github.com/google/go-sev-guest v0.12.1/go.mod h1:SK9vW+uyfuzYdVN0m8BShL3OQCtXZe/JPF7ZkpD3760=
github.com/google/go-sev-guest v0.13.0 h1:DJB6ACdykyweMU0HGOp/TQ7cjsnbV2ecbYunu2E0qy0=
github.com/google/go-sev-guest v0.13.0/go.mod h1:SK9vW+uyfuzYdVN0m8BShL3OQCtXZe/JPF7ZkpD3760=
github.com/google/go-tdx-guest v0.3.2-0.20241009005452-097ee70d0843 h1:+MoPobRN9HrDhGyn6HnF5NYo4uMBKaiFqAtf/D/OB4A=
github.com/google/go-tdx-guest v0.3.2-0.20241009005452-097ee70d0843/go.mod h1:g/n8sKITIT9xRivBUbizo34DTsUm2nN2uU3A662h09g=
github.com/google/go-tpm v0.9.3 h1:+yx0/anQuGzi+ssRqeD6WpXjW2L/V0dItUayO0i9sRc=
@@ -396,6 +430,8 @@ github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLe
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg=
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/trillian v1.3.14-0.20210409160123-c5ea3abd4a41/go.mod h1:1dPv0CUjNQVFEDuAUFhZql16pw/VlPgaX8qj+g5pVzQ=
github.com/google/trillian v1.3.14-0.20210511103300-67b5f349eefa/go.mod h1:s4jO3Ai4NSvxucdvqUHON0bCqJyoya32eNw6XJwsmNc=
@@ -407,9 +443,14 @@ github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs16741s=
github.com/googleapis/enterprise-certificate-proxy v0.3.5 h1:VgzTY2jogw3xt39CusEnFJWm7rlsq5yL5q9XdLOuP5g=
github.com/googleapis/enterprise-certificate-proxy v0.3.5/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
github.com/googleapis/gax-go v2.0.2+incompatible h1:silFMLAnr330+NRuag/VjIGF7TLp/LBrV2CJKFLWEww=
github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q=
github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
github.com/goreleaser/goreleaser v0.134.0/go.mod h1:ZT6Y2rSYa6NxQzIsdfWWNWAlYGXGbreo66NmE+3X3WQ=
@@ -635,6 +676,8 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
@@ -825,12 +868,17 @@ go.opencensus.io v0.22.6/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
go.opentelemetry.io/contrib v0.20.0 h1:ubFQUn0VCZ0gPwIoJfBJVpeBlyRMxu8Mm/huKWYd9p0=
go.opentelemetry.io/contrib v0.20.0/go.mod h1:G/EtFaa6qaN7+LxqfIAT3GiZa7Wv5DTBUzl5H4LY0Kc=
go.opentelemetry.io/contrib/detectors/gcp v1.34.0 h1:JRxssobiPg23otYU5SbWtQC//snGVIM3Tx6QRzlQBao=
go.opentelemetry.io/contrib/detectors/gcp v1.34.0/go.mod h1:cV4BMFcscUR/ckqLkbfQmF0PRsq8w/lMGzdbCSveBHo=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.20.0/go.mod h1:oVGt1LRbBOBq1A5BQLlUg9UaU/54aiHw8cgjV3aWZ/E=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0 h1:rgMkmiGfix9vFJDcDi1PK8WEQP4FLQwLDfhp5ZLpFeE=
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.59.0/go.mod h1:ijPqXp5P6IRRByFVVg9DY8P5HkxkHE5ARIa+86aXPf4=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0 h1:DheMAlT6POBP+gh8RUH19EOTnQIor5QE0uSRPtzCpSw=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.57.0/go.mod h1:wZcGmeVO9nzP67aYSLDqXNWK87EZWhi7JWj1v7ZXf94=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0 h1:CV7UdSGJt/Ao6Gp4CXckLxVRRsRgDHoI8XjbL3PDl8s=
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.59.0/go.mod h1:FRmFuRJfag1IZ2dPkHnEoSFVgTVPUd2qf5Vi69hLb8I=
go.opentelemetry.io/otel v0.20.0/go.mod h1:Y3ugLH2oa81t5QO+Lty+zXf8zC9L26ax4Nzoxm/dooo=
go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
@@ -846,10 +894,14 @@ go.opentelemetry.io/otel/oteltest v0.20.0/go.mod h1:L7bgKf9ZB7qCwT9Up7i9/pn0PWIa
go.opentelemetry.io/otel/sdk v0.20.0/go.mod h1:g/IcepuwNsoiX5Byy2nNV0ySUF1em498m7hBWC279Yc=
go.opentelemetry.io/otel/sdk v1.32.0 h1:RNxepc9vK59A8XsgZQouW8ue8Gkb4jpWtJm9ge5lEG4=
go.opentelemetry.io/otel/sdk v1.32.0/go.mod h1:LqgegDBjKMmb2GC6/PrTnteJG39I8/vJCAP9LlJXEjU=
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
go.opentelemetry.io/otel/sdk/export/metric v0.20.0/go.mod h1:h7RBNMsDJ5pmI1zExLi+bJK+Dr8NQCh0qGhm1KDnNlE=
go.opentelemetry.io/otel/sdk/metric v0.20.0/go.mod h1:knxiS8Xd4E/N+ZqKmUPf3gTTZ4/0TjTXukfxjzSTpHE=
go.opentelemetry.io/otel/sdk/metric v1.32.0 h1:rZvFnvmvawYb0alrYkjraqJq0Z4ZUJAiyYCU9snn1CU=
go.opentelemetry.io/otel/sdk/metric v1.32.0/go.mod h1:PWeZlq0zt9YkYAp3gjKZ0eicRYvOh1Gd+X99x6GHpCQ=
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
go.opentelemetry.io/otel/trace v0.20.0/go.mod h1:6GjCW8zgDjwGHGa6GkyeB8+/5vjT16gUEi0Nf1iBdgw=
go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
@@ -983,6 +1035,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8=
golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -1002,6 +1056,8 @@ golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.28.0 h1:CrgCKl8PPAVtLnU3c+EDw6x11699EWlsDeWNWKdIOkc=
golang.org/x/oauth2 v0.28.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -1016,6 +1072,8 @@ golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w=
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -1114,6 +1172,8 @@ golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxb
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.6.0 h1:eTDhh4ZXt5Qf0augr54TN6suAUudPcawVZeIAPU7D4U=
golang.org/x/time v0.6.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/time v0.10.0 h1:3usCWA8tQn0L8+hFJQNgzpWbd89begxN66o1Ojdn5L4=
golang.org/x/time v0.10.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -1222,6 +1282,8 @@ google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtuk
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
google.golang.org/api v0.224.0 h1:Ir4UPtDsNiwIOHdExr3fAj4xZ42QjK7uQte3lORLJwU=
google.golang.org/api v0.224.0/go.mod h1:3V39my2xAGkodXy0vEqcEtkqgw2GtrFL5WuBZlCTCOQ=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -1295,10 +1357,16 @@ google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKr
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb h1:ITgPrl429bc6+2ZraNSzMDk3I95nmQln2fuPstKwFDE=
google.golang.org/genproto v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:sAo5UzpjUwgFBCzupwhcLcxHVDK7vG5IqI30YnwX2eE=
google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489 h1:fCuMM4fowGzigT89NCIsW57Pk9k2D12MMi2ODn+Nk+o=
google.golang.org/genproto/googleapis/api v0.0.0-20250204164813-702378808489/go.mod h1:iYONQfRdizDB8JJBybql13nArx91jcUk7zCXEsOofM4=
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb h1:p31xT4yrYrSM/G4Sn2+TNUkVhFCbG9y8itM2S6Th950=
google.golang.org/genproto/googleapis/api v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:jbe3Bkdp+Dh2IrslsFCklNhweNTBgSYanP1UXhJDhKg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6 h1:2duwAxN2+k0xLNpjnHTXoMUgnv6VPSp5fiqTuwSxjmI=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250207221924-e9438ea467c6/go.mod h1:8BS3B93F/U1juMFq9+EDk+qOT5CO1R9IzXxG3PTqiRk=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb h1:TLPQVbx1GJ8VKZxz52VAxl1EBgKXXbTiU9Fc5fZeLn4=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250303144028-a0af3efb3deb/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
google.golang.org/grpc v1.8.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -1333,6 +1401,8 @@ google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
+107 -113
View File
@@ -6,64 +6,66 @@ Manager service provides a barebones gRPC API and Service interface implementati
The service is configured using the environment variables from the following table. Note that any unset variables will be replaced with their default values.
| Variable | Description | Default |
| ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------- | ---------------------------- |
| COCOS_JAEGER_URL | The URL for the Jaeger tracing endpoint. | http://localhost:4318 |
| COCOS_JAEGER_TRACE_RATIO | The ratio of traces to sample. | 1.0 |
| MANAGER_INSTANCE_ID | The instance ID for the manager service. | |
| MANAGER_ATTESTATION_POLICY_BINARY | The file path for the attestation policy and igvmmeassure binaries. | ../../build |
| MANAGER_GRPC_CLIENT_CERT | The file path for the client certificate. | |
| MANAGER_GRPC_CLIENT_KEY | The file path for the client private key. | |
| MANAGER_GRPC_SERVER_CA_CERTS | The file path for the server CA certificate(s). | |
| MANAGER_GRPC_URL | The URL for the gRPC endpoint. | localhost:7001 |
| MANAGER_GRPC_TIMEOUT | The timeout for gRPC requests. | 60s |
| MANAGER_EOS_VERSION | The EOS version used for booting SVMs. | |
| MANAGER_INSTANCE_ID | Manager service instance ID | |
| MANAGER_QEMU_MEMORY_SIZE | The total memory size for the virtual machine. Can be specified in a human-readable format like "2048M" or "4G". | 2048M |
| MANAGER_QEMU_MEMORY_SLOTS | The number of memory slots for the virtual machine. | 5 |
| MANAGER_QEMU_MAX_MEMORY | The maximum memory size for the virtual machine. Can be specified in a human-readable format like "30G". | 30G |
| MANAGER_QEMU_OVMF_CODE_IF | The interface type for the OVMF code. | pflash |
| MANAGER_QEMU_OVMF_CODE_FORMAT | The format of the OVMF code file. | raw |
| MANAGER_QEMU_OVMF_CODE_UNIT | The unit number for the OVMF code. | 0 |
| MANAGER_QEMU_OVMF_CODE_FILE | The file path for the OVMF code. | /usr/share/OVMF/OVMF_CODE.fd |
| MANAGER_QEMU_OVMF_VERSION | The version number of EDKII from which OVMF was built | edk2-stable202408 |
| MANAGER_QEMU_OVMF_CODE_READONLY | Whether the OVMF code should be read-only. | on |
| MANAGER_QEMU_OVMF_VARS_IF | The interface type for the OVMF variables. | pflash |
| MANAGER_QEMU_OVMF_VARS_FORMAT | The format of the OVMF variables file. | raw |
| MANAGER_QEMU_OVMF_VARS_UNIT | The unit number for the OVMF variables. | 1 |
| MANAGER_QEMU_OVMF_VARS_FILE | The file path for the OVMF variables. | /usr/share/OVMF/OVMF_VARS.fd |
| MANAGER_QEMU_NETDEV_ID | The ID for the network device. | vmnic |
| MANAGER_QEMU_HOST_FWD_AGENT | The port number for the host forward agent. | 7020 |
| MANAGER_QEMU_GUEST_FWD_AGENT | The port number for the guest forward agent. | 7002 |
| MANAGER_QEMU_VIRTIO_NET_PCI_DISABLE_LEGACY | Whether to disable the legacy PCI device. | on |
| MANAGER_QEMU_VIRTIO_NET_PCI_IOMMU_PLATFORM | Whether to enable the IOMMU platform for the virtio-net PCI device. | true |
| MANAGER_QEMU_VIRTIO_NET_PCI_ADDR | The PCI address for the virtio-net PCI device. | 0x2 |
| MANAGER_QEMU_VIRTIO_NET_PCI_ROMFILE | The file path for the ROM image for the virtio-net PCI device. | |
| MANAGER_QEMU_DISK_IMG_KERNEL_FILE | The file path for the kernel image. | img/bzImage |
| MANAGER_QEMU_DISK_IMG_ROOTFS_FILE | The file path for the root filesystem image. | img/rootfs.cpio.gz |
| MANAGER_QEMU_SEV_ID | The ID for the Secure Encrypted Virtualization (SEV) device. | sev0 |
| MANAGER_QEMU_SEV_CBITPOS | The position of the C-bit in the physical address. | 51 |
| MANAGER_QEMU_SEV_REDUCED_PHYS_BITS | The number of reduced physical address bits for SEV. | 1 |
| MANAGER_QEMU_ENABLE_HOST_DATA | Enable additional data for the SEV host. | false |
| MANAGER_QEMU_HOST_DATA | Additional data for the SEV host. | |
| MANAGER_QEMU_IGVM_ID | The ID of the IGVM file. | igvm0 |
| MANAGER_QEMU_IGVM_FILE | The file path to the IGVM file. | /root/coconut-qemu.igvm |
| MANAGER_QEMU_VSOCK_ID | The ID for the virtual socket device. | vhost-vsock-pci0 |
| MANAGER_QEMU_VSOCK_GUEST_CID | The guest-side CID (Context ID) for the virtual socket device. | 3 |
| MANAGER_QEMU_VSOCK_VNC | Whether to enable the virtual socket device for VNC. | 0 |
| MANAGER_QEMU_BIN_PATH | The file path for the QEMU binary. | qemu-system-x86_64 |
| MANAGER_QEMU_USE_SUDO | Whether to use sudo to run QEMU. | false |
| MANAGER_QEMU_ENABLE_SEV | Whether to enable Secure Encrypted Virtualization (SEV). | false |
| MANAGER_QEMU_ENABLE_SEV_SNP | Whether to enable Secure Nested Paging (SEV-SNP). | true |
| MANAGER_QEMU_ENABLE_KVM | Whether to enable the Kernel-based Virtual Machine (KVM) acceleration. | true |
| MANAGER_QEMU_MACHINE | The machine type for QEMU. | q35 |
| MANAGER_QEMU_CPU | The CPU model for QEMU. | EPYC |
| MANAGER_QEMU_SMP_COUNT | The number of virtual CPUs. | 4 |
| MANAGER_QEMU_SMP_MAXCPUS | The maximum number of virtual CPUs. | 64 |
| MANAGER_QEMU_MEM_ID | The ID for the memory device. | ram1 |
| MANAGER_QEMU_NO_GRAPHIC | Whether to disable the graphical display. | true |
| MANAGER_QEMU_MONITOR | The type of monitor to use. | pty |
| MANAGER_QEMU_HOST_FWD_RANGE | The range of host ports to forward. | 6100-6200 |
| Variable | Description | Default |
| ------------------------------------------ | ---------------------------------------------------------------------------------------------------------------- | ------------------------------ |
| COCOS_JAEGER_URL | The URL for the Jaeger tracing endpoint. | http://localhost:4318 |
| COCOS_JAEGER_TRACE_RATIO | The ratio of traces to sample. | 1.0 |
| MANAGER_INSTANCE_ID | The instance ID for the manager service. | |
| MANAGER_ATTESTATION_POLICY_BINARY | The file path for the attestation policy binarie. | ../../build/attestation_policy |
| MANAGER_IGVMMEASURE_BINARY | The file path for the igvmmeasure binarie. | ../../build/igvmmeasure |
| MANAGER_PCR_VALUES | The file path for the file with the expected PCR values. | |
| MANAGER_GRPC_CLIENT_CERT | The file path for the client certificate. | |
| MANAGER_GRPC_CLIENT_KEY | The file path for the client private key. | |
| MANAGER_GRPC_SERVER_CA_CERTS | The file path for the server CA certificate(s). | |
| MANAGER_GRPC_URL | The URL for the gRPC endpoint. | localhost:7001 |
| MANAGER_GRPC_TIMEOUT | The timeout for gRPC requests. | 60s |
| MANAGER_EOS_VERSION | The EOS version used for booting SVMs. | |
| MANAGER_INSTANCE_ID | Manager service instance ID | |
| MANAGER_QEMU_MEMORY_SIZE | The total memory size for the virtual machine. Can be specified in a human-readable format like "2048M" or "4G". | 2048M |
| MANAGER_QEMU_MEMORY_SLOTS | The number of memory slots for the virtual machine. | 5 |
| MANAGER_QEMU_MAX_MEMORY | The maximum memory size for the virtual machine. Can be specified in a human-readable format like "30G". | 30G |
| MANAGER_QEMU_OVMF_CODE_IF | The interface type for the OVMF code. | pflash |
| MANAGER_QEMU_OVMF_CODE_FORMAT | The format of the OVMF code file. | raw |
| MANAGER_QEMU_OVMF_CODE_UNIT | The unit number for the OVMF code. | 0 |
| MANAGER_QEMU_OVMF_CODE_FILE | The file path for the OVMF code. | /usr/share/OVMF/OVMF_CODE.fd |
| MANAGER_QEMU_OVMF_VERSION | The version number of EDKII from which OVMF was built | edk2-stable202408 |
| MANAGER_QEMU_OVMF_CODE_READONLY | Whether the OVMF code should be read-only. | on |
| MANAGER_QEMU_OVMF_VARS_IF | The interface type for the OVMF variables. | pflash |
| MANAGER_QEMU_OVMF_VARS_FORMAT | The format of the OVMF variables file. | raw |
| MANAGER_QEMU_OVMF_VARS_UNIT | The unit number for the OVMF variables. | 1 |
| MANAGER_QEMU_OVMF_VARS_FILE | The file path for the OVMF variables. | /usr/share/OVMF/OVMF_VARS.fd |
| MANAGER_QEMU_NETDEV_ID | The ID for the network device. | vmnic |
| MANAGER_QEMU_HOST_FWD_AGENT | The port number for the host forward agent. | 7020 |
| MANAGER_QEMU_GUEST_FWD_AGENT | The port number for the guest forward agent. | 7002 |
| MANAGER_QEMU_VIRTIO_NET_PCI_DISABLE_LEGACY | Whether to disable the legacy PCI device. | on |
| MANAGER_QEMU_VIRTIO_NET_PCI_IOMMU_PLATFORM | Whether to enable the IOMMU platform for the virtio-net PCI device. | true |
| MANAGER_QEMU_VIRTIO_NET_PCI_ADDR | The PCI address for the virtio-net PCI device. | 0x2 |
| MANAGER_QEMU_VIRTIO_NET_PCI_ROMFILE | The file path for the ROM image for the virtio-net PCI device. | |
| MANAGER_QEMU_DISK_IMG_KERNEL_FILE | The file path for the kernel image. | img/bzImage |
| MANAGER_QEMU_DISK_IMG_ROOTFS_FILE | The file path for the root filesystem image. | img/rootfs.cpio.gz |
| MANAGER_QEMU_SEV_ID | The ID for the Secure Encrypted Virtualization (SEV) device. | sev0 |
| MANAGER_QEMU_SEV_CBITPOS | The position of the C-bit in the physical address. | 51 |
| MANAGER_QEMU_SEV_REDUCED_PHYS_BITS | The number of reduced physical address bits for SEV. | 1 |
| MANAGER_QEMU_ENABLE_HOST_DATA | Enable additional data for the SEV host. | false |
| MANAGER_QEMU_HOST_DATA | Additional data for the SEV host. | |
| MANAGER_QEMU_IGVM_ID | The ID of the IGVM file. | igvm0 |
| MANAGER_QEMU_IGVM_FILE | The file path to the IGVM file. | /root/coconut-qemu.igvm |
| MANAGER_QEMU_VSOCK_ID | The ID for the virtual socket device. | vhost-vsock-pci0 |
| MANAGER_QEMU_VSOCK_GUEST_CID | The guest-side CID (Context ID) for the virtual socket device. | 3 |
| MANAGER_QEMU_VSOCK_VNC | Whether to enable the virtual socket device for VNC. | 0 |
| MANAGER_QEMU_BIN_PATH | The file path for the QEMU binary. | qemu-system-x86_64 |
| MANAGER_QEMU_USE_SUDO | Whether to use sudo to run QEMU. | false |
| MANAGER_QEMU_ENABLE_SEV | Whether to enable Secure Encrypted Virtualization (SEV). | false |
| MANAGER_QEMU_ENABLE_SEV_SNP | Whether to enable Secure Nested Paging (SEV-SNP). | true |
| MANAGER_QEMU_ENABLE_KVM | Whether to enable the Kernel-based Virtual Machine (KVM) acceleration. | true |
| MANAGER_QEMU_MACHINE | The machine type for QEMU. | q35 |
| MANAGER_QEMU_CPU | The CPU model for QEMU. | EPYC |
| MANAGER_QEMU_SMP_COUNT | The number of virtual CPUs. | 4 |
| MANAGER_QEMU_SMP_MAXCPUS | The maximum number of virtual CPUs. | 64 |
| MANAGER_QEMU_MEM_ID | The ID for the memory device. | ram1 |
| MANAGER_QEMU_NO_GRAPHIC | Whether to disable the graphical display. | true |
| MANAGER_QEMU_MONITOR | The type of monitor to use. | pty |
| MANAGER_QEMU_HOST_FWD_RANGE | The range of host ports to forward. | 6100-6200 |
## Setup
@@ -90,21 +92,11 @@ sudo apt install qemu-kvm
Create `img` directory in `cmd/manager`.
#### Add Vsock
The necessary kernel modules must be loaded on the hypervisor. To check if `vhost_vsock` is loaded run:
```shell
lsmod | grep vhost_vsock
```
#### Virtual filesystem
If `vhost_vsock` is not loaded run the following commands:
9P (or Plan 9 Filesystem) in QEMU is a lightweight, network-based file-sharing protocol. In Cocos, the 9P is used to transfer environment variables and TLS certificates for cloud communication from the Manager to the Agent.
```shell
sudo modprobe vhost_vsock
ls -l /dev/vhost-vsock
# crw-rw-rw- 1 root kvm 10, 241 Jan 16 12:05 /dev/vhost-vsock
ls -l /dev/vsock
# crw-rw-rw- 1 root root 10, 121 Jan 16 12:05 /dev/vsock
```
You should define the environment variables in a file called environment. For the number and meaning of the environment variables, please refer to the Agent [Readme](https://github.com/ultravioletrs/cocos/blob/main/agent/README.md).
### Prepare Cocos HAL
@@ -124,10 +116,32 @@ OVMF_CODE=/usr/share/OVMF/OVMF_CODE.fd
sudo find / -name OVMF_VARS.fd
# => /usr/share/OVMF/OVMF_VARS.fd
OVMF_VARS=/usr/share/OVMF/OVMF_VARS.fd
# Create a local copy of OVMF_VARS.
cp /usr/share/OVMF/OVMF_VARS.fd .
# Create a directory for the environment file and the certificates for cloud certificates.
mkdir env
mkdir certs
# Enter the env directory and create the environemnt file.
cd env
touch environment
# Define Computations endpoint URL for agent.
# Make sure the Computation endpoint is running (like Cocos Prism).
echo AGENT_CVM_GRPC_URL=localhost:7001 >> ./environment
# Define log level for the agent.
echo AGENT_LOG_LEVEL=debug >> ./environment
# Return to cmd/manager
cd ..
OVMF_VARS=./OVMF_VARS.fd
KERNEL="img/bzImage"
INITRD="img/rootfs.cpio.gz"
ENV_PATH=./env
CERTH_PATH=./certs
qemu-system-x86_64 \
-enable-kvm \
@@ -137,15 +151,19 @@ qemu-system-x86_64 \
-m 2048M,slots=5,maxmem=10240M \
-no-reboot \
-drive if=pflash,format=raw,unit=0,file=$OVMF_CODE,readonly=on \
-drive if=pflash,format=raw,unit=1,file=$OVMF_VARS \
-netdev user,id=vmnic,hostfwd=tcp::7020-:7002 \
-device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= \
-device vhost-vsock-pci,id=vhost-vsock-pci0,guest-cid=3 -vnc :0 \
-kernel $KERNEL \
-append "earlyprintk=serial console=ttyS0" \
-initrd $INITRD \
-nographic \
-monitor pty \
-monitor unix:monitor,server,nowait
-monitor unix:monitor,server,nowait \
-fsdev local,id=env_fs,path=$ENV_PATH,security_model=mapped \
-device virtio-9p-pci,fsdev=env_fs,mount_tag=env_share \
-fsdev local,id=cert_fs,path=$CERTH_PATH,security_model=mapped \
-device virtio-9p-pci,fsdev=cert_fs,mount_tag=certs_share
```
Once the VM is booted press enter and on the login use username `root`.
@@ -190,10 +208,21 @@ MANAGER_QEMU_OVMF_VARS_FILE=/usr/share/OVMF/OVMF_VARS.fd
NB: we set environment variables that we will use in the shell process where we run `manager`.
### Trusted Platform Module (TPM)
The Trusted Platform Module (TPM) plays a fundamental role in this process by providing a tamper-resistant foundation for cryptographic operations, securing sensitive artifacts, measuring system state, and enabling attestation mechanisms.
### IGVM
An IGVM file contains all the necessary information to launch a virtual machine on different virtualization platforms. It includes setup commands for the guest system and verification data to ensure the VM is loaded securely and correctly.
Cocos uses the [COCONUT-SVSM](https://github.com/coconut-svsm/svsm/blob/main/Documentation/docs/installation/INSTALL.md) for the vTPM. The IGVM file contains the OVMF file and the vTPM.
## Deployment
To start the service, execute the following shell script (note a server needs to be running see [here](../test/cvms/README.md)):
To start the service, execute the following shell script (note a server needs to be running see [here](../test/cvms/README.md)):
The manager can be started as a *systemd* service or a standalone executable. To start the manager as a systemd service, look at the systemd service script [here](https://github.com/ultravioletrs/cocos/blob/main/init/systemd/cocos-manager.service). The environment variables are defined in the `cocos-manager.env` file. Below are examples of how to start the manager.
```bash
# Download the latest version of the service
@@ -205,13 +234,14 @@ cd cocos
make manager
# Set the environment variables and run the service
MANAGER_GRPC_URL=localhost:7001
MANAGER_GRPC_URL=localhost:7001 \
MANAGER_LOG_LEVEL=debug \
MANAGER_QEMU_USE_SUDO=false \
MANAGER_QEMU_ENABLE_SEV=false \
./build/cocos-manager
```
To enable [AMD SEV](https://www.amd.com/en/developer/sev.html) support, start manager like this
```sh
@@ -223,7 +253,7 @@ MANAGER_QEMU_SEV_CBITPOS=51 \
./build/cocos-manager
```
To build the OVMF with the kernel hash capability, we must build the AmdSev package of OVMF. The result of the build should be a single `OVMF.fd` file (unlike the regular two OVFM files). The OVMF package is located at `OvmfPkg/AmdSev/AmdSevX64.dsc`.
To start SEV-SNP, define the IGVM file that contains the vTPM and the OVMF (combined OVMF_CODE and OVMF_VARS) of the CVM.
To enable [AMD SEV-SNP](https://www.amd.com/en/developer/sev.html) support, start manager like this
@@ -238,42 +268,6 @@ MANAGER_QEMU_IGVM_FILE=<path to IGVM file> \
./build/cocos-manager
```
### Verifying VM launch
NB: To verify that the manager successfully launched the VM, you need to open three terminals on the same machine. In one terminal, you need to launch the computations server by executing (with the environment variables of choice):
```bash
go run ./test/computations/main.go <dataset path> <algo path>
```
and in the second the manager by executing (with the environment variables of choice):
```bash
go run ./cmd/manager/main.go
```
Ensure that the Manager can connect to the Manager test server by setting the MANAGER_GRPC_PORT with the port value of the Manager test server. In the last terminal, you can run the verification commands.
To verify that the manager launched the VM successfully, run the following command:
```sh
ps aux | grep qemu-system-x86_64
```
You should get something similar to this
```
darko 324763 95.3 6.0 6398136 981044 ? Sl 16:17 0:15 /usr/bin/qemu-system-x86_64 -enable-kvm -machine q35 -cpu EPYC -smp 4,maxcpus=64 -m 4096M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=/usr/share/OVMF/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=img/OVMF_VARS.fd -device virtio-scsi-pci,id=scsi,disable-legacy=on,iommu_platform=true -drive file=img/focal-server-cloudimg-amd64.img,if=none,id=disk0,format=qcow2 -device scsi-hd,drive=disk0 -netdev user,id=vmnic,hostfwd=tcp::2222-:22,hostfwd=tcp::9301-:9031,hostfwd=tcp::7020-:7002 -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= -nographic -monitor pty
```
If you run a command as `sudo`, you should get the output similar to this one
```
root 37982 0.0 0.0 9444 4572 pts/0 S+ 16:18 0:00 sudo /usr/local/bin/qemu-system-x86_64 -enable-kvm -machine q35 -cpu EPYC -smp 4,maxcpus=64 -m 4096M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=/usr/share/OVMF/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=img/OVMF_VARS.fd -device virtio-scsi-pci,id=scsi,disable-legacy=on,iommu_platform=true -drive file=img/focal-server-cloudimg-amd64.img,if=none,id=disk0,format=qcow2 -device scsi-hd,drive=disk0 -netdev user,id=vmnic,hostfwd=tcp::2222-:22,hostfwd=tcp::9301-:9031,hostfwd=tcp::7020-:7002 -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= -object sev-guest,id=sev0,cbitpos=51,reduced-phys-bits=1 -machine memory-encryption=sev0 -nographic -monitor pty
root 37989 122 13.1 5345816 4252312 pts/0 Sl+ 16:19 0:04 /usr/local/bin/qemu-system-x86_64 -enable-kvm -machine q35 -cpu EPYC -smp 4,maxcpus=64 -m 4096M,slots=5,maxmem=30G -drive if=pflash,format=raw,unit=0,file=/usr/share/OVMF/OVMF_CODE.fd,readonly=on -drive if=pflash,format=raw,unit=1,file=img/OVMF_VARS.fd -device virtio-scsi-pci,id=scsi,disable-legacy=on,iommu_platform=true -drive file=img/focal-server-cloudimg-amd64.img,if=none,id=disk0,format=qcow2 -device scsi-hd,drive=disk0 -netdev user,id=vmnic,hostfwd=tcp::2222-:22,hostfwd=tcp::9301-:9031,hostfwd=tcp::7020-:7002 -device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= -object sev-guest,id=sev0,cbitpos=51,reduced-phys-bits=1 -machine memory-encryption=sev0 -nographic -monitor pty
```
The two processes are due to the fact that we run the command `/usr/bin/qemu-system-x86_64` as `sudo`, so there is one process for `sudo` command and the other for `/usr/bin/qemu-system-x86_64`.
### Troubleshooting
If the `ps aux | grep qemu-system-x86_64` give you something like this
+43 -28
View File
@@ -11,24 +11,38 @@ import (
"bytes"
"context"
"encoding/base64"
"encoding/hex"
"encoding/json"
"fmt"
"os"
"os/exec"
"strconv"
"strings"
"github.com/google/go-sev-guest/proto/check"
"github.com/ultravioletrs/cocos/manager/qemu"
"github.com/ultravioletrs/cocos/pkg/attestation/igvmmeasure"
config "github.com/ultravioletrs/cocos/pkg/attestation"
"github.com/ultravioletrs/cocos/pkg/attestation/cmdconfig"
"github.com/virtee/sev-snp-measure-go/cpuid"
"github.com/virtee/sev-snp-measure-go/guest"
"github.com/virtee/sev-snp-measure-go/vmmtypes"
"google.golang.org/protobuf/encoding/protojson"
)
const defGuestFeatures = 0x1
func (ms *managerService) FetchAttestationPolicy(_ context.Context, computationId string) ([]byte, error) {
cmd := exec.Command("sudo", fmt.Sprintf("%s/attestation_policy", ms.attestationPolicyBinaryPath), "--policy", "196608")
var stderrBuffer bytes.Buffer
options := []string{"--policy", "196608"}
if ms.pcrValuesFilePath != "" {
pcrValues := []string{"--pcr", ms.pcrValuesFilePath}
options = append(options, pcrValues...)
}
stderr := bufio.NewWriter(&stderrBuffer)
attestPolicyCmd, err := cmdconfig.NewCmdConfig("sudo", options, stderr)
if err != nil {
return nil, err
}
ms.mu.Lock()
vm, exists := ms.vms[computationId]
@@ -43,22 +57,15 @@ func (ms *managerService) FetchAttestationPolicy(_ context.Context, computationI
}
ms.ap.Lock()
_, err := cmd.Output()
stdOutByte, err := attestPolicyCmd.Run(ms.attestationPolicyBinaryPath)
ms.ap.Unlock()
if err != nil {
return nil, err
}
ms.ap.Lock()
f, err := os.ReadFile("./attestation_policy.json")
ms.ap.Unlock()
if err != nil {
return nil, err
}
attestationPolicy := config.Config{Config: &check.Config{RootOfTrust: &check.RootOfTrust{}, Policy: &check.Policy{}}, PcrConfig: &config.PcrConfig{}}
var attestationPolicy check.Config
if err = protojson.Unmarshal(f, &attestationPolicy); err != nil {
if err = config.ReadAttestationPolicyFromByte(stdOutByte, &attestationPolicy); err != nil {
return nil, err
}
@@ -70,29 +77,37 @@ func (ms *managerService) FetchAttestationPolicy(_ context.Context, computationI
return nil, err
}
case vmi.Config.EnableSEVSNP:
igvmMeasurementBinaryPath := fmt.Sprintf("%s/igvmmeasure", ms.attestationPolicyBinaryPath)
var stdoutBuffer bytes.Buffer
var stderrBuffer bytes.Buffer
stdout := bufio.NewWriter(&stdoutBuffer)
stderr := bufio.NewWriter(&stderrBuffer)
options := cmdconfig.IgvmMeasureOptions
igvmMeasurement, err := igvmmeasure.NewIgvmMeasurement(igvmMeasurementBinaryPath, stderr, stdout)
igvmMeasurement, err := cmdconfig.NewCmdConfig(ms.igvmMeasurementBinaryPath, options, stderr)
if err != nil {
return nil, err
}
err = igvmMeasurement.Run(ms.qemuCfg.IGVMConfig.File)
outputByte, err := igvmMeasurement.Run(ms.qemuCfg.IGVMConfig.File)
if err != nil {
return nil, err
}
measurement = stdoutBuffer.Bytes()
outputString := string(outputByte)
lines := strings.Split(strings.TrimSpace(outputString), "\n")
if len(lines) == 1 {
outputString = strings.TrimSpace(outputString)
outputString = strings.ToLower(outputString)
} else {
return nil, fmt.Errorf("error: %s", outputString)
}
measurement, err = hex.DecodeString(outputString)
if err != nil {
return nil, err
}
}
if measurement != nil {
attestationPolicy.Policy.Measurement = measurement
attestationPolicy.Config.Policy.Measurement = measurement
}
if vmi.Config.SevConfig.EnableHostData {
@@ -100,12 +115,12 @@ func (ms *managerService) FetchAttestationPolicy(_ context.Context, computationI
if err != nil {
return nil, err
}
attestationPolicy.Policy.HostData = hostData
attestationPolicy.Config.Policy.HostData = hostData
}
attestationPolicy.Policy.MinimumLaunchTcb = vmi.LaunchTCB
attestationPolicy.Config.Policy.MinimumLaunchTcb = vmi.LaunchTCB
f, err = protojson.Marshal(&attestationPolicy)
f, err := json.MarshalIndent(attestationPolicy, "", " ")
if err != nil {
return nil, err
}
+5 -3
View File
@@ -6,6 +6,7 @@ import (
"context"
"encoding/json"
"os"
"path"
"path/filepath"
"testing"
@@ -20,7 +21,7 @@ func CreateDummyAttestationPolicyBinary(t *testing.T, behavior string) string {
switch behavior {
case "success":
content = []byte(`#!/bin/sh
echo '{"policy": {"measurement": null, "host_data": null}}' > attestation_policy.json
echo '{"pcr_values": {"sha256": null, "sha384": null}, "policy": {"measurement": null, "host_data": null}}'
`)
case "fail":
content = []byte(`#!/bin/sh
@@ -105,7 +106,7 @@ func TestFetchAttestationPolicy(t *testing.T) {
},
LaunchTCB: 0,
},
expectedError: "no such file or directory",
expectedError: "failed to decode Attestation Policy file",
},
}
@@ -116,7 +117,8 @@ func TestFetchAttestationPolicy(t *testing.T) {
ms := &managerService{
vms: make(map[string]vm.VM),
attestationPolicyBinaryPath: tempDir,
attestationPolicyBinaryPath: path.Join(tempDir, "attestation_policy"),
pcrValuesFilePath: tempDir,
qemuCfg: qemu.Config{
CPU: "EPYC",
},
+2 -2
View File
@@ -3,8 +3,8 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.4
// protoc v5.29.3
// protoc-gen-go v1.36.5
// protoc v5.29.0
// source: manager/manager.proto
package manager
+1 -1
View File
@@ -4,7 +4,7 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.5.1
// - protoc v5.29.3
// - protoc v5.29.0
// source: manager/manager.proto
package manager
+26 -14
View File
@@ -3,13 +3,14 @@
package manager
import (
"bufio"
"bytes"
"context"
"encoding/base64"
"fmt"
"log/slog"
"net"
"os"
"os/exec"
"regexp"
"strconv"
"sync"
@@ -21,6 +22,7 @@ import (
"github.com/ultravioletrs/cocos/manager/qemu"
"github.com/ultravioletrs/cocos/manager/vm"
config "github.com/ultravioletrs/cocos/pkg/attestation"
"github.com/ultravioletrs/cocos/pkg/attestation/cmdconfig"
"github.com/ultravioletrs/cocos/pkg/manager"
"golang.org/x/crypto/sha3"
)
@@ -85,6 +87,8 @@ type managerService struct {
ap sync.Mutex
qemuCfg qemu.Config
attestationPolicyBinaryPath string
igvmMeasurementBinaryPath string
pcrValuesFilePath string
logger *slog.Logger
vms map[string]vm.VM
vmFactory vm.Provider
@@ -97,7 +101,7 @@ type managerService struct {
var _ Service = (*managerService)(nil)
// New instantiates the manager service implementation.
func New(cfg qemu.Config, attestationPolicyBinPath string, logger *slog.Logger, vmFactory vm.Provider, eosVersion string) (Service, error) {
func New(cfg qemu.Config, attestationPolicyBinPath string, igvmMeasurementBinaryPath string, pcrValuesFilePath string, logger *slog.Logger, vmFactory vm.Provider, eosVersion string) (Service, error) {
start, end, err := decodeRange(cfg.HostFwdRange)
if err != nil {
return nil, err
@@ -114,6 +118,8 @@ func New(cfg qemu.Config, attestationPolicyBinPath string, logger *slog.Logger,
vms: make(map[string]vm.VM),
vmFactory: vmFactory,
attestationPolicyBinaryPath: attestationPolicyBinPath,
igvmMeasurementBinaryPath: igvmMeasurementBinaryPath,
pcrValuesFilePath: pcrValuesFilePath,
portRangeMin: start,
portRangeMax: end,
persistence: persistence,
@@ -150,30 +156,36 @@ func (ms *managerService) CreateVM(ctx context.Context, req *CreateReq) (string,
cfg.Config.EnvMount = tmpEnvDir
if ms.qemuCfg.EnableSEVSNP || ms.qemuCfg.EnableSEV {
cmd := exec.Command("sudo", fmt.Sprintf("%s/attestation_policy", ms.attestationPolicyBinaryPath), "--policy", "196608")
var stderrBuffer bytes.Buffer
options := []string{"--policy", "196608"}
if ms.pcrValuesFilePath != "" {
pcrValues := []string{"--pcr", ms.pcrValuesFilePath}
options = append(options, pcrValues...)
}
stderr := bufio.NewWriter(&stderrBuffer)
attestPolicyCmd, err := cmdconfig.NewCmdConfig("sudo", options, stderr)
if err != nil {
return "", id, err
}
ms.ap.Lock()
_, err := cmd.Output()
stdOutByte, err := attestPolicyCmd.Run(ms.attestationPolicyBinaryPath)
ms.ap.Unlock()
if err != nil {
return "", id, errors.Wrap(ErrFailedToCreateAttestationPolicy, err)
}
ms.ap.Lock()
f, err := os.ReadFile("./attestation_policy.json")
ms.ap.Unlock()
if err != nil {
return "", id, errors.Wrap(ErrFailedToReadPolicy, err)
}
attestationPolicy := config.Config{Config: &check.Config{RootOfTrust: &check.RootOfTrust{}, Policy: &check.Policy{}}, PcrConfig: &config.PcrConfig{}}
attestationPolicy := config.Config{SnpCheck: &check.Config{RootOfTrust: &check.RootOfTrust{}, Policy: &check.Policy{}}, PcrConfig: &config.PcrConfig{}}
if err = config.ReadAttestationPolicyFromByte(f, &attestationPolicy); err != nil {
if err = config.ReadAttestationPolicyFromByte(stdOutByte, &attestationPolicy); err != nil {
return "", id, errors.Wrap(ErrUnmarshalFailed, err)
}
// Define the TCB that was present at launch of the VM.
cfg.LaunchTCB = attestationPolicy.SnpCheck.Policy.MinimumLaunchTcb
cfg.LaunchTCB = attestationPolicy.Config.Policy.MinimumLaunchTcb
}
agentPort, err := getFreePort(ms.portRangeMin, ms.portRangeMax)
+4 -2
View File
@@ -9,6 +9,7 @@ import (
"net"
"os"
"os/exec"
"path"
"testing"
mglog "github.com/absmach/magistrala/logger"
@@ -29,7 +30,7 @@ func TestNew(t *testing.T) {
logger := slog.Default()
vmf := new(mocks.Provider)
service, err := New(cfg, "", logger, vmf.Execute, "")
service, err := New(cfg, "", "", "", logger, vmf.Execute, "")
require.NoError(t, err)
assert.NotNil(t, service)
@@ -94,7 +95,8 @@ func TestRun(t *testing.T) {
ms := &managerService{
qemuCfg: qemuCfg,
attestationPolicyBinaryPath: tempDir,
attestationPolicyBinaryPath: path.Join(tempDir, "attestation_policy"),
pcrValuesFilePath: tempDir,
logger: logger,
vms: make(map[string]vm.VM),
vmFactory: vmf.Execute,
@@ -1,48 +1,46 @@
// Copyright (c) Ultraviolet
// SPDX-License-Identifier: Apache-2.0
package igvmmeasure
package cmdconfig
import (
"bytes"
"fmt"
"io"
"os/exec"
"strings"
)
var IgvmMeasureOptions = []string{"measure", "-b"}
type MeasurementProvider interface {
Run(igvmBinaryPath string) error
Run(binaryPath string) ([]byte, error)
Stop() error
}
type IgvmMeasurement struct {
type CmdConfig struct {
binPath string
options []string
stderr io.Writer
stdout io.Writer
cmd *exec.Cmd
execCommand func(name string, arg ...string) *exec.Cmd
}
func NewIgvmMeasurement(binPath string, stderr, stdout io.Writer) (*IgvmMeasurement, error) {
func NewCmdConfig(binPath string, options []string, stderr io.Writer) (*CmdConfig, error) {
if binPath == "" {
return nil, fmt.Errorf("pathToBinary cannot be empty")
}
return &IgvmMeasurement{
return &CmdConfig{
binPath: binPath,
options: options,
stderr: stderr,
stdout: stdout,
execCommand: exec.Command,
}, nil
}
func (m *IgvmMeasurement) Run(pathToFile string) error {
func (m *CmdConfig) Run(pathToFile string) ([]byte, error) {
binary := m.binPath
args := []string{}
args = append(args, m.options...)
args = append(args, pathToFile)
args = append(args, "measure")
args = append(args, "-b")
args = append(args, m.options...)
outBuf := &bytes.Buffer{}
cmd := m.execCommand(binary, args...)
@@ -50,26 +48,13 @@ func (m *IgvmMeasurement) Run(pathToFile string) error {
cmd.Stdout = outBuf
if err := cmd.Run(); err != nil {
return err
}
outputString := outBuf.String()
lines := strings.Split(strings.TrimSpace(outputString), "\n")
if len(lines) == 1 {
outputString = strings.ToLower(outputString)
_, err := m.stdout.Write([]byte(outputString))
if err != nil {
return err
}
} else {
return fmt.Errorf("error: %s", outputString)
return nil, err
}
return nil
return outBuf.Bytes(), nil
}
func (m *IgvmMeasurement) Stop() error {
func (m *CmdConfig) Stop() error {
if m.cmd == nil || m.cmd.Process == nil {
return fmt.Errorf("no running process to stop")
}
@@ -82,6 +67,6 @@ func (m *IgvmMeasurement) Stop() error {
}
// SetExecCommand allows tests to inject a mock execCommand function.
func (m *IgvmMeasurement) SetExecCommand(cmdFunc func(name string, arg ...string) *exec.Cmd) {
func (m *CmdConfig) SetExecCommand(cmdFunc func(name string, arg ...string) *exec.Cmd) {
m.execCommand = cmdFunc
}
@@ -1,6 +1,6 @@
// Copyright (c) Ultraviolet
// SPDX-License-Identifier: Apache-2.0
package igvmmeasure
package cmdconfig
import (
"bytes"
@@ -14,15 +14,15 @@ import (
func TestIgvmMeasurement(t *testing.T) {
tests := []struct {
name string
setup func() *IgvmMeasurement
setup func() *CmdConfig
runArgs string
expectErr bool
expectedErr string
}{
{
name: "NewIgvmMeasurement - Empty pathToBinary",
setup: func() *IgvmMeasurement {
igvm, err := NewIgvmMeasurement("", nil, nil)
setup: func() *CmdConfig {
igvm, err := NewCmdConfig("", []string{""}, nil)
assert.Error(t, err)
assert.Nil(t, igvm)
return nil
@@ -32,8 +32,8 @@ func TestIgvmMeasurement(t *testing.T) {
},
{
name: "Run - Successful Execution",
setup: func() *IgvmMeasurement {
igvm, _ := NewIgvmMeasurement("/valid/path", nil, nil)
setup: func() *CmdConfig {
igvm, _ := NewCmdConfig("/valid/path", []string{""}, nil)
igvm.SetExecCommand(func(name string, arg ...string) *exec.Cmd {
return exec.Command("sh", "-c", "echo 'measurement successful'")
})
@@ -43,8 +43,8 @@ func TestIgvmMeasurement(t *testing.T) {
},
{
name: "Run - Failure Execution",
setup: func() *IgvmMeasurement {
igvm, _ := NewIgvmMeasurement("/invalid/path", nil, nil)
setup: func() *CmdConfig {
igvm, _ := NewCmdConfig("/invalid/path", []string{""}, nil)
igvm.SetExecCommand(func(name string, arg ...string) *exec.Cmd {
return exec.Command("sh", "-c", "echo 'some error occurred\nextra line' && exit 1")
})
@@ -61,10 +61,9 @@ func TestIgvmMeasurement(t *testing.T) {
if igvm != nil {
buf := new(bytes.Buffer)
igvm.stdout = buf
igvm.stderr = buf
err := igvm.Run(tc.runArgs)
_, err := igvm.Run(tc.runArgs)
if tc.expectErr {
assert.Error(t, err)
assert.Equal(t, strings.TrimSpace(tc.expectedErr), strings.TrimSpace(err.Error()))
+6 -4
View File
@@ -21,15 +21,17 @@ const (
)
var (
AttestationPolicy = Config{SnpCheck: &check.Config{Policy: &check.Policy{}, RootOfTrust: &check.RootOfTrust{}}, PcrConfig: &PcrConfig{}}
AttestationPolicy = Config{Config: &check.Config{Policy: &check.Policy{}, RootOfTrust: &check.RootOfTrust{}}, PcrConfig: &PcrConfig{}}
ErrAttestationPolicyOpen = errors.New("failed to open Attestation Policy file")
ErrAttestationPolicyDecode = errors.New("failed to decode Attestation Policy file")
ErrAttestationPolicyMissing = errors.New("failed due to missing Attestation Policy file")
ErrAttestationPolicyEncode = errors.New("failed to encode the Attestation Policy")
)
type PcrValues struct {
Sha256 map[string]string `json:"sha256"`
Sha384 map[string]string `json:"sha384"`
Sha1 map[string]string `json:"sha1"`
}
type PcrConfig struct {
@@ -37,8 +39,8 @@ type PcrConfig struct {
}
type Config struct {
SnpCheck *check.Config
PcrConfig *PcrConfig
*check.Config
*PcrConfig
}
func ReadAttestationPolicy(policyPath string, attestationConfiguration *Config) error {
@@ -57,7 +59,7 @@ func ReadAttestationPolicy(policyPath string, attestationConfiguration *Config)
func ReadAttestationPolicyFromByte(policyData []byte, attestationConfiguration *Config) error {
unmarshalOptions := protojson.UnmarshalOptions{AllowPartial: true, DiscardUnknown: true}
if err := unmarshalOptions.Unmarshal(policyData, attestationConfiguration.SnpCheck); err != nil {
if err := unmarshalOptions.Unmarshal(policyData, attestationConfiguration.Config); err != nil {
return errors.Wrap(ErrAttestationPolicyDecode, err)
}
+111
View File
@@ -0,0 +1,111 @@
// Copyright (c) Ultraviolet
// SPDX-License-Identifier: Apache-2.0
package gcp
import (
"context"
"fmt"
"io"
"cloud.google.com/go/storage"
"github.com/golang/protobuf/proto"
"github.com/google/gce-tcb-verifier/proto/endorsement"
"github.com/google/go-sev-guest/proto/check"
"github.com/google/go-sev-guest/proto/sevsnp"
"github.com/google/go-sev-guest/tools/lib/report"
config "github.com/ultravioletrs/cocos/pkg/attestation"
)
const (
// Offset of the 384-bit measurement in the report.
// The measurement is 48 bytes long and starts at offset 0x90.
// https://www.amd.com/content/dam/amd/en/documents/epyc-technical-docs/specifications/56860.pdf page 56
measurementOffset = 0x90
measurementSize = 48
bucketName = "gce_tcb_integrity"
objectName = "ovmf_x64_csm/sevsnp/%s.binarypb"
ovmfObjectName = "ovmf_x64_csm/%s.fd"
)
func Extract384BitMeasurement(attestation *sevsnp.Attestation) (string, error) {
if attestation == nil {
return "", fmt.Errorf("report is nil")
}
reportBin, err := report.Transform(attestation, "bin")
if err != nil {
return "", fmt.Errorf("failed to transform report to binary: %v", err)
}
if len(reportBin) < measurementOffset+measurementSize {
return "", fmt.Errorf("report is too short to contain the 384-bit measurement")
}
measurement := reportBin[measurementOffset : measurementOffset+measurementSize]
return fmt.Sprintf("%x", measurement), nil
}
func GetLaunchEndorsement(ctx context.Context, measurement384 string) (*endorsement.VMGoldenMeasurement, error) {
client, err := storage.NewClient(ctx)
if err != nil {
return &endorsement.VMGoldenMeasurement{}, fmt.Errorf("failed to create storage client: %v", err)
}
reader, err := client.Bucket(bucketName).Object(fmt.Sprintf(objectName, measurement384)).NewReader(ctx)
if err != nil {
return &endorsement.VMGoldenMeasurement{}, fmt.Errorf("failed to create reader: %v", err)
}
defer reader.Close()
launchEndorsements, err := io.ReadAll(reader)
if err != nil {
return &endorsement.VMGoldenMeasurement{}, fmt.Errorf("failed to read object: %v", err)
}
var endorsementPB endorsement.VMLaunchEndorsement
if err := proto.Unmarshal(launchEndorsements, &endorsementPB); err != nil {
return &endorsement.VMGoldenMeasurement{}, fmt.Errorf("failed to unmarshal launch endorsement: %v", err)
}
var goldenUEFI endorsement.VMGoldenMeasurement
if err := proto.Unmarshal(endorsementPB.SerializedUefiGolden, &goldenUEFI); err != nil {
return &endorsement.VMGoldenMeasurement{}, fmt.Errorf("failed to unmarshal golden UEFI: %v", err)
}
return &goldenUEFI, nil
}
func GenerateAttestationPolicy(endorsement *endorsement.VMGoldenMeasurement, vcpuNum uint32) (*config.Config, error) {
attestationPolicy := config.Config{PcrConfig: &config.PcrConfig{}, Config: &check.Config{RootOfTrust: &check.RootOfTrust{}, Policy: &check.Policy{}}}
attestationPolicy.Config.Policy.Policy = endorsement.SevSnp.Policy
attestationPolicy.Config.Policy.Measurement = endorsement.SevSnp.Measurements[vcpuNum]
attestationPolicy.Config.RootOfTrust.DisallowNetwork = false
attestationPolicy.Config.RootOfTrust.CheckCrl = true
attestationPolicy.Config.RootOfTrust.Product = "Milan"
attestationPolicy.Config.RootOfTrust.ProductLine = "Milan"
return &attestationPolicy, nil
}
func DownloadOvmfFile(ctx context.Context, digest string) ([]byte, error) {
client, err := storage.NewClient(ctx)
if err != nil {
return []byte{}, fmt.Errorf("failed to create storage client: %v", err)
}
reader, err := client.Bucket(bucketName).Object(fmt.Sprintf(ovmfObjectName, digest)).NewReader(ctx)
if err != nil {
return []byte{}, fmt.Errorf("failed to create reader: %v", err)
}
defer reader.Close()
ovmf, err := io.ReadAll(reader)
if err != nil {
return []byte{}, fmt.Errorf("failed to read object: %v", err)
}
return ovmf, nil
}
+1 -1
View File
@@ -142,7 +142,7 @@ func GetLeveledQuoteProvider() (client.LeveledQuoteProvider, error) {
}
func VerifyAttestationReportTLS(attestationPB *sevsnp.Attestation, reportData []byte) error {
config, err := copyConfig(config.AttestationPolicy.SnpCheck)
config, err := copyConfig(config.AttestationPolicy.Config)
if err != nil {
return errors.Wrap(fmt.Errorf("failed to create a copy of attestation policy"), err)
}
+11 -11
View File
@@ -145,8 +145,8 @@ func TestVerifyAttestationReportUnknownProduct(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
config.AttestationPolicy.SnpCheck.RootOfTrust.ProductLine = ""
config.AttestationPolicy.SnpCheck.Policy.Product = nil
config.AttestationPolicy.Config.RootOfTrust.ProductLine = ""
config.AttestationPolicy.Config.Policy.Product = nil
err := VerifyAttestationReportTLS(tt.attestationReport, tt.reportData)
assert.True(t, errors.Contains(err, tt.err), fmt.Sprintf("expected error %v, got %v", tt.err, err))
})
@@ -192,23 +192,23 @@ func prepVerifyAttReport(t *testing.T) (*sevsnp.Attestation, []byte) {
rr, err := abi.ReportCertsToProto(file)
require.NoError(t, err)
config.AttestationPolicy = config.Config{SnpCheck: &check.Config{Policy: &check.Policy{}, RootOfTrust: &check.RootOfTrust{}}, PcrConfig: &config.PcrConfig{}}
config.AttestationPolicy = config.Config{Config: &check.Config{Policy: &check.Policy{}, RootOfTrust: &check.RootOfTrust{}}, PcrConfig: &config.PcrConfig{}}
attestationPolicyFile, err := os.ReadFile("../../../scripts/attestation_policy/attestation_policy.json")
require.NoError(t, err)
unmarshalOptions := protojson.UnmarshalOptions{DiscardUnknown: true}
err = unmarshalOptions.Unmarshal(attestationPolicyFile, config.AttestationPolicy.SnpCheck)
err = unmarshalOptions.Unmarshal(attestationPolicyFile, config.AttestationPolicy.Config)
require.NoError(t, err)
config.AttestationPolicy.SnpCheck.Policy.Product = &sevsnp.SevProduct{Name: sevsnp.SevProduct_SEV_PRODUCT_MILAN}
config.AttestationPolicy.SnpCheck.Policy.FamilyId = rr.Report.FamilyId
config.AttestationPolicy.SnpCheck.Policy.ImageId = rr.Report.ImageId
config.AttestationPolicy.SnpCheck.Policy.Measurement = rr.Report.Measurement
config.AttestationPolicy.SnpCheck.Policy.HostData = rr.Report.HostData
config.AttestationPolicy.SnpCheck.Policy.ReportIdMa = rr.Report.ReportIdMa
config.AttestationPolicy.SnpCheck.RootOfTrust.ProductLine = sevProductNameMilan
config.AttestationPolicy.Config.Policy.Product = &sevsnp.SevProduct{Name: sevsnp.SevProduct_SEV_PRODUCT_MILAN}
config.AttestationPolicy.Config.Policy.FamilyId = rr.Report.FamilyId
config.AttestationPolicy.Config.Policy.ImageId = rr.Report.ImageId
config.AttestationPolicy.Config.Policy.Measurement = rr.Report.Measurement
config.AttestationPolicy.Config.Policy.HostData = rr.Report.HostData
config.AttestationPolicy.Config.Policy.ReportIdMa = rr.Report.ReportIdMa
config.AttestationPolicy.Config.RootOfTrust.ProductLine = sevProductNameMilan
return rr, rr.Report.ReportData
}
+14 -11
View File
@@ -126,7 +126,7 @@ func VTPMVerify(quote []byte, pubKeyTLS []byte, teeNonce []byte, vtpmNonce []byt
err := proto.Unmarshal(quote, attestation)
if err != nil {
return fmt.Errorf("fail to unmarshal quote: %v", err)
return errors.Wrap(fmt.Errorf("failed to unmarshal quote"), err)
}
ak := attestation.GetAkPub()
@@ -142,7 +142,7 @@ func VTPMVerify(quote []byte, pubKeyTLS []byte, teeNonce []byte, vtpmNonce []byt
reportData, err := createTEEAttestationReportNonce(pubKeyTLS, ak, teeNonce)
if err != nil {
return fmt.Errorf("fail to calculate report data: %v", err)
return errors.Wrap(fmt.Errorf("failed to create TEE attestation report nonce"), err)
}
if err := quoteprovider.VerifyAttestationReportTLS(attestation.GetSevSnpAttestation(), reportData); err != nil {
@@ -151,7 +151,7 @@ func VTPMVerify(quote []byte, pubKeyTLS []byte, teeNonce []byte, vtpmNonce []byt
_, err = server.VerifyAttestation(attestation, server.VerifyOpts{Nonce: vtpmNonce, TrustedAKs: []crypto.PublicKey{cryptoPub}})
if err != nil {
return fmt.Errorf("verifying attestation: %w", err)
return errors.Wrap(fmt.Errorf("failed to verify attestation"), err)
}
s256, s384 := calculatePCRTLSKey(pubKeyTLS)
@@ -196,7 +196,7 @@ func createTEEAttestationReportNonce(pubKeyTLS []byte, ak []byte, nonce []byte)
func marshalQuote(attestation *attest.Attestation) ([]byte, error) {
out, err := proto.Marshal(attestation)
if err != nil {
return []byte{}, fmt.Errorf("failed to marshal vTPM attestation report: %v", err)
return []byte{}, errors.Wrap(fmt.Errorf("failed to marshal vTPM attestation report"), err)
}
return out, nil
@@ -211,7 +211,7 @@ func fetchVTPMQuote(nonce []byte) (*attest.Attestation, error) {
attestationKey, err := client.AttestationKeyRSA(rwc)
if err != nil {
return nil, fmt.Errorf("failed to create attestation key: %v", err)
return nil, errors.Wrap(fmt.Errorf("failed to create attestation key: %v", err), err)
}
defer attestationKey.Close()
@@ -222,12 +222,12 @@ func fetchVTPMQuote(nonce []byte) (*attest.Attestation, error) {
attestOpts.TCGEventLog, err = client.GetEventLog(rwc)
if err != nil {
return nil, fmt.Errorf("failed to retrieve TCG Event Log: %w", err)
return nil, errors.Wrap(fmt.Errorf("failed to retrieve TCG Event Log: %v", err), err)
}
attestation, err := attestationKey.Attest(attestOpts)
if err != nil {
return nil, fmt.Errorf("failed to collect attestation report: %v", err)
return nil, errors.Wrap(fmt.Errorf("failed to attest: %v", err), err)
}
return attestation, nil
@@ -241,7 +241,7 @@ func addTEEAttestation(attestation *attest.Attestation, nonce []byte) (*attest.A
extReport, err := abi.ReportCertsToProto(rawTeeAttestation)
if err != nil {
return attestation, fmt.Errorf("failed to export the TEE report: %v", err)
return attestation, errors.Wrap(fmt.Errorf("failed to convert TEE report to proto"), err)
}
attestation.TeeAttestation = &attest.Attestation_SevSnpAttestation{
SevSnpAttestation: extReport,
@@ -250,7 +250,7 @@ func addTEEAttestation(attestation *attest.Attestation, nonce []byte) (*attest.A
return attestation, nil
}
func checkExpectedPCRValues(attestation *attest.Attestation, ePcr256 []byte, ePcr384 []byte) error {
func checkExpectedPCRValues(attestation *attest.Attestation, ePcr256, ePcr384 []byte) error {
quotes := attestation.GetQuotes()
for i := range quotes {
quote := quotes[i]
@@ -263,6 +263,9 @@ func checkExpectedPCRValues(attestation *attest.Attestation, ePcr256 []byte, ePc
case tpm.HashAlgo_SHA384:
pcrMap = config.AttestationPolicy.PcrConfig.PCRValues.Sha384
pcr15 = ePcr384
case tpm.HashAlgo_SHA1:
pcrMap = config.AttestationPolicy.PcrConfig.PCRValues.Sha1
pcr15 = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
default:
return errors.Wrap(ErrNoHashAlgo, fmt.Errorf("algo: %s", tpm.HashAlgo_name[int32(quote.Pcrs.Hash)]))
}
@@ -275,11 +278,11 @@ func checkExpectedPCRValues(attestation *attest.Attestation, ePcr256 []byte, ePc
for i, v := range pcrMap {
index, err := strconv.ParseInt(i, 10, 32)
if err != nil {
return fmt.Errorf("error converting PCR index to int32: %v\n", err)
return errors.Wrap(fmt.Errorf("error converting PCR index to int32"), err)
}
value, err := hex.DecodeString(v)
if err != nil {
return fmt.Errorf("error converting PCR value to byte: %v\n", err)
return errors.Wrap(fmt.Errorf("error converting PCR value to byte"), err)
}
if !bytes.Equal(quote.Pcrs.Pcrs[uint32(index)], value) {
return fmt.Errorf("for algo %s PCR[%d] expected %s but found %s", tpm.HashAlgo_name[int32(quote.Pcrs.Hash)], index, hex.EncodeToString(value), hex.EncodeToString(quote.Pcrs.Pcrs[uint32(index)]))
+3 -3
View File
@@ -251,13 +251,13 @@ func TestReadAttestationPolicy(t *testing.T) {
defer os.Remove(tt.manifestPath)
}
config := att.Config{SnpCheck: &check.Config{}, PcrConfig: &att.PcrConfig{}}
config := att.Config{Config: &check.Config{}, PcrConfig: &att.PcrConfig{}}
err := att.ReadAttestationPolicy(tt.manifestPath, &config)
assert.True(t, errors.Contains(err, tt.err), fmt.Sprintf("expected error %v, got %v", tt.err, err))
if tt.err == nil {
assert.NotNil(t, config.SnpCheck.Policy)
assert.NotNil(t, config.SnpCheck.RootOfTrust)
assert.NotNil(t, config.Config.Policy)
assert.NotNil(t, config.Config.RootOfTrust)
}
})
}
+1 -1
View File
@@ -15,5 +15,5 @@ Then run the binary. Keep in mind that you have to specify the policy of the Gue
cd ./target/release
# Run with option --policy (policy is 64 bit number)
./attestation_policy --policy 196608
./attestation_policy --policy 196608 --pcr ../../pcr_values.json
```
+25 -25
View File
@@ -4,11 +4,7 @@ use serde::Serialize;
use serde_json::Value;
use sev::firmware::host::*;
use std::arch::x86_64::__cpuid;
use std::fs::{read_to_string, File};
use std::io::Write;
const ATTESTATION_POLICY_JSON: &str = "attestation_policy.json";
const PCR_VALUES_JSON: &str = "pcr_values.json";
use std::fs::read_to_string;
const EXTENDED_FAMILY_SHIFT: u32 = 20;
const EXTENDED_MODEL_SHIFT: u32 = 16;
@@ -118,8 +114,18 @@ fn main() {
.required(true)
.value_parser(value_parser!(u64)),
)
.arg(
Arg::new("pcr")
.long("pcr")
.value_name("FILE")
.help("Optional path to the PCR values JSON file")
.required(false),
)
.get_matches();
// If provided, get the PCR file path.
let pcr_path = matches.get_one::<String>("pcr");
let mut firmware: Firmware = Firmware::open().unwrap();
let status: SnpPlatformStatus = firmware.snp_platform_status().unwrap();
@@ -175,33 +181,27 @@ fn main() {
let mut computation_value =
serde_json::to_value(&computation).expect("Failed to convert computation to JSON");
// Read and parse the pcr_values.json file.
let pcr_content = read_to_string(PCR_VALUES_JSON).expect("Failed to read pcr_values.json");
let pcr_value: Value =
serde_json::from_str(&pcr_content).expect("Failed to parse pcr_values.json");
// If the PCR file path was provided, read and merge its JSON content.
if let Some(pcr_path) = pcr_path {
let pcr_content = read_to_string(pcr_path)
.unwrap_or_else(|_| panic!("Failed to read PCR file at {}", pcr_path));
let pcr_value: Value = serde_json::from_str(&pcr_content)
.unwrap_or_else(|_| panic!("Failed to parse PCR JSON file at {}", pcr_path));
// Merge the pcr_values into the main JSON object.
if let Value::Object(ref mut main_map) = computation_value {
if let Value::Object(pcr_map) = pcr_value {
// The keys in pcr_map (e.g., "pcr_values") will be added
main_map.extend(pcr_map);
if let Value::Object(ref mut main_map) = computation_value {
if let Value::Object(pcr_map) = pcr_value {
main_map.extend(pcr_map);
} else {
eprintln!("PCR file {} is not a JSON object.", pcr_path);
}
} else {
eprintln!("{} is not a JSON object.", PCR_VALUES_JSON);
eprintln!("The computed JSON is not an object.");
}
} else {
eprintln!("The computed JSON is not an object.");
}
// Serialize the merged JSON and write to file.
let merged_json =
serde_json::to_string_pretty(&computation_value).expect("Failed to serialize merged JSON");
let mut file =
File::create(ATTESTATION_POLICY_JSON).expect("Failed to create attestation policy file");
file.write_all(merged_json.as_bytes())
.expect("Failed to write merged JSON to file");
println!(
"AttestationPolicy JSON has been written to {}",
ATTESTATION_POLICY_JSON
);
println!("{}", merged_json);
}
+14 -7
View File
@@ -22,14 +22,11 @@ Agent is started automatically in the VM when launched but requires configuratio
For attested TLS, you will have to calculate the VM's measurement, which can be done using cli. This information is also contained in the Attestation Policy file.
```bash
# Define the path to the OVMF, KERNEL, INITRD and CMD Kernel line arguments.
OVMF_CODE="/home/cocosai/ovmf/Build/AmdSev/DEBUG_GCC5/FV/OVMF.fd"
INITRD="/home/cocosai/initramfs.cpio.gz"
KERNEL="/home/cocosai/bzImage"
LINE="earlyprintk=serial console=ttyS0"
# Define the path to the IGVM file that contains the vTPM and the OVMF.
IGVM="<path to the IGVM file>"
# Call sev-snp-measure
./build/cocos-cli sevsnpmeasure --mode snp --vcpus 4 --vcpu-type EPYC-v4 --ovmf $OVMF_CODE --kernel $KERNEL --initrd $INITRD --append "$LINE"
# Call igvmmeasure
./build/cocos-cli igvmmeasure $IGVM
```
To speed up the verification process of attested TLS, download the ARK and ASK certificates using the CLI tool. The CLI tool will download the certificates under your home directory in the `.cocos` directory.
@@ -48,6 +45,10 @@ export AGENT_GRPC_URL=localhost:7002
cd scripts/attestation_policy
make
sudo ./target/release/attestation_policy --policy 196608 # Default value of the policy should be 196608
# In order to include the golden (good) PCR values in the attestation policy, call the attestation policy script with the "--pcr" option.
sudo ./target/release/attestation_policy --policy 196608 --pcr ./pcr_values.json
# The output file attestation_policy.json will be generated in the directory from which the executable has been called.
cd ../..
@@ -81,6 +82,12 @@ export AGENT_GRPC_ATTESTED_TLS=true
# Product name must be Milan or Genoa
./build/cocos-cli attestation validate '<attesation>' --report_data '<report_data>' --product <product_name>
# Other options for attestation validation using the CLI are:
# validate <attestationreportfilepath> --report_data <reportdata> --product <product data> //default
# validate --mode snp <attestationreportfilepath> --report_data <reportdata> --product <product data>
# validate --mode vtpm <attestationreportfilepath> --nonce <noncevalue> --format <formatvalue> --output <outputvalue>
# validate --mode snp-vtpm <attestationreportfilepath> --nonce <noncevalue> --format <formatvalue> --output <outputvalue>
# Run the CLI program with algorithm input
./build/cocos-cli algo test/manual/algo/lin_reg.py <private_key_file_path> -a python -r test/manual/algo/requirements.py
# 2023/09/21 10:43:53 Uploading algorithm binary: test/manual/algo/lin_reg.bin
+213 -31
View File
@@ -38,31 +38,121 @@ python3 test/manual/algo/lin_reg.py predict results.zip test/manual/data
This will make inference on the results of the linear regression model.
To run the examples in the secure VM (SVM) by the Agent, you can use the following command:
To run the examples in the confidential VM (CVM) or a regular VM by the Agent, you can use the following command:
```bash
go run ./test/computations/main.go ./test/manual/algo/lin_reg.py public.pem false ./test/manual/data/iris.csv
go run ./test/cvms/main.go ./test/manual/algo/lin_reg.py public.pem false ./test/manual/data/iris.csv
```
This command is run from the root directory of the project. This will start the computation server.
This command is run from the root directory of the project. This will start the CVM server.
In another window, you can run the following command:
For a regular VM, in another window, run the following command:
```bash
sudo find / -name OVMF_CODE.fd
# => /usr/share/OVMF/OVMF_CODE.fd
OVMF_CODE=/usr/share/OVMF/OVMF_CODE.fd
sudo find / -name OVMF_VARS.fd
# => /usr/share/OVMF/OVMF_VARS.fd
# Create a local copy of OVMF_VARS.
cp /usr/share/OVMF/OVMF_VARS.fd .
OVMF_VARS=./OVMF_VARS.fd
# Create a directory for the environment file and the certificates for cloud certificates.
mkdir env
mkdir certs
# Enter the env directory and create the environemnt file.
cd env
touch environment
# Define Computations endpoint URL for agent.
# Make sure the Computation endpoint is running (like Cocos Prism).
echo AGENT_CVM_GRPC_URL=localhost:7001 >> ./environment
# Define log level for the agent.
echo AGENT_LOG_LEVEL=debug >> ./environment
cd ..
KERNEL=<path to kernel built with HAL>
INITRD=<path to initial RAM file system built with HAL>
APPEND="earlyprintk=serial console=ttyS0"
QEMU_BIN=<path to QEMU binary>
ENV_PATH=./env
CERTH_PATH=./certs
$QEMU_BIN -enable-kvm \
-smp 4 \
-m 8G,slots=5,maxmem=10G \
-cpu EPYC-v4 \
-machine q35 \
-no-reboot \
-drive if=pflash,format=raw,unit=0,file=$OVMF_CODE,readonly=on \
-drive if=pflash,format=raw,unit=1,file=$OVMF_VARS \
-netdev user,id=vmnic,hostfwd=tcp::7020-:7002 \
-device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic \
-initrd $INITRD \
-kernel $KERNEL -append $APPEND \
-nographic \
-monitor pty \
-monitor unix:monitor,server,nowait \
-fsdev local,id=env_fs,path=$ENV_PATH,security_model=mapped \
-device virtio-9p-pci,fsdev=env_fs,mount_tag=env_share \
-fsdev local,id=cert_fs,path=$CERTH_PATH,security_model=mapped \
-device virtio-9p-pci,fsdev=cert_fs,mount_tag=certs_share
```
For a CVM, in another window, run the following command:
```bash
sudo \
MANAGER_QEMU_SMP_MAXCPUS=4 \
MANAGER_GRPC_URL=localhost:7001 \
MANAGER_LOG_LEVEL=debug \
MANAGER_QEMU_USE_SUDO=false \
MANAGER_QEMU_ENABLE_SEV=false \
MANAGER_QEMU_SEV_CBITPOS=51 \
MANAGER_QEMU_ENABLE_SEV_SNP=false \
MANAGER_QEMU_OVMF_CODE_FILE=/usr/share/edk2/x64/OVMF_CODE.fd \
MANAGER_QEMU_OVMF_VARS_FILE=/usr/share/edk2/x64/OVMF_VARS.fd \
go run main.go
# Create a directory for the environment file and the certificates for cloud certificates.
mkdir env
mkdir certs
# Enter the env directory and create the environemnt file.
cd env
touch environment
# Define Computations endpoint URL for agent.
# Make sure the Computation endpoint is running (like Cocos Prism).
echo AGENT_CVM_GRPC_URL=localhost:7001 >> ./environment
# Define log level for the agent.
echo AGENT_LOG_LEVEL=debug >> ./environment
cd ..
KERNEL=<path to kernel built with HAL>
INITRD=<path to initial RAM file system built with HAL>
APPEND="earlyprintk=serial console=ttyS0"
IGVM=<path to IGVM file>
QEMU_BIN=<path to QEMU binary>
ENV_PATH=./env
CERTH_PATH=./certs
$QEMU_BIN -enable-kvm \
-enable-kvm \
-cpu EPYC-v4 \
-machine q35 \
-smp 4,maxcpus=16 \
-m 8G,slots=5,maxmem=30G \
-netdev user,id=vmnic,hostfwd=tcp::7020-:7002 \
-device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= \
-machine confidential-guest-support=sev0,memory-backend=ram1,igvm-cfg=igvm0 \
-object memory-backend-memfd,id=ram1,size=8G,share=true,prealloc=false,reserve=false \
-object sev-snp-guest,id=sev0,cbitpos=51,reduced-phys-bits=1 \
-object igvm-cfg,id=igvm0,file=$IGVM \
-initrd $INITRD \
-kernel $KERNEL -append $APPEND \
-nographic \
-monitor pty \
-monitor unix:monitor,server,nowait \
-fsdev local,id=env_fs,path=$ENV_PATH,security_model=mapped \
-device virtio-9p-pci,fsdev=env_fs,mount_tag=env_share \
-fsdev local,id=cert_fs,path=$CERTH_PATH,security_model=mapped \
-device virtio-9p-pci,fsdev=cert_fs,mount_tag=certs_share
```
This command is run from the [manager main directory](../../../cmd/manager/). This will start the manager. Make sure you have already built the [qemu image](../../../hal/linux/README.md).
Make sure you have already built the [qemu image](../../../hal/linux/README.md) and the IGVM file from the COCONUT-SVSM [repository](https://github.com/coconut-svsm/svsm/blob/main/Documentation/docs/installation/INSTALL.md).
In another window, you can run the following command:
@@ -125,29 +215,121 @@ docker build -t linreg .
docker save linreg > linreg.tar
```
To run the examples in the secure VM (SVM) by the Agent, you can use the following command in cocos root directory `/cocos`:
To run the examples in the confidential VM (CVM) or a regular VM by the Agent, you can use the following command:
```bash
go run ./test/computations/main.go ./test/manual/algo/linreg.tar public.pem false ./test/manual/data/iris.csv
go run ./test/cvms/main.go ./test/manual/algo/lin_reg.py public.pem false ./test/manual/data/iris.csv
```
In another window, you can run the following command in the `cmd/manager` directory:
This command is run from the root directory of the project. This will start the CVM server.
For a regular VM, in another window, run the following command:
```bash
sudo find / -name OVMF_CODE.fd
# => /usr/share/OVMF/OVMF_CODE.fd
OVMF_CODE=/usr/share/OVMF/OVMF_CODE.fd
sudo find / -name OVMF_VARS.fd
# => /usr/share/OVMF/OVMF_VARS.fd
# Create a local copy of OVMF_VARS.
cp /usr/share/OVMF/OVMF_VARS.fd .
OVMF_VARS=./OVMF_VARS.fd
# Create a directory for the environment file and the certificates for cloud certificates.
mkdir env
mkdir certs
# Enter the env directory and create the environemnt file.
cd env
touch environment
# Define Computations endpoint URL for agent.
# Make sure the Computation endpoint is running (like Cocos Prism).
echo AGENT_CVM_GRPC_URL=localhost:7001 >> ./environment
# Define log level for the agent.
echo AGENT_LOG_LEVEL=debug >> ./environment
cd ..
KERNEL=<path to kernel built with HAL>
INITRD=<path to initial RAM file system built with HAL>
APPEND="earlyprintk=serial console=ttyS0"
QEMU_BIN=<path to QEMU binary>
ENV_PATH=./env
CERTH_PATH=./certs
$QEMU_BIN -enable-kvm \
-smp 4 \
-m 8G,slots=5,maxmem=10G \
-cpu EPYC-v4 \
-machine q35 \
-no-reboot \
-drive if=pflash,format=raw,unit=0,file=$OVMF_CODE,readonly=on \
-drive if=pflash,format=raw,unit=1,file=$OVMF_VARS \
-netdev user,id=vmnic,hostfwd=tcp::7020-:7002 \
-device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic \
-initrd $INITRD \
-kernel $KERNEL -append $APPEND \
-nographic \
-monitor pty \
-monitor unix:monitor,server,nowait \
-fsdev local,id=env_fs,path=$ENV_PATH,security_model=mapped \
-device virtio-9p-pci,fsdev=env_fs,mount_tag=env_share \
-fsdev local,id=cert_fs,path=$CERTH_PATH,security_model=mapped \
-device virtio-9p-pci,fsdev=cert_fs,mount_tag=certs_share
```
For a CVM, in another window, run the following command:
```bash
sudo \
MANAGER_QEMU_SMP_MAXCPUS=4 \
MANAGER_GRPC_URL=localhost:7001 \
MANAGER_LOG_LEVEL=debug \
MANAGER_QEMU_USE_SUDO=false \
MANAGER_QEMU_ENABLE_SEV=false \
MANAGER_QEMU_SEV_CBITPOS=51 \
MANAGER_QEMU_ENABLE_SEV_SNP=false \
MANAGER_QEMU_OVMF_CODE_FILE=/usr/share/edk2/x64/OVMF_CODE.fd \
MANAGER_QEMU_OVMF_VARS_FILE=/usr/share/edk2/x64/OVMF_VARS.fd \
go run main.go
# Create a directory for the environment file and the certificates for cloud certificates.
mkdir env
mkdir certs
# Enter the env directory and create the environemnt file.
cd env
touch environment
# Define Computations endpoint URL for agent.
# Make sure the Computation endpoint is running (like Cocos Prism).
echo AGENT_CVM_GRPC_URL=localhost:7001 >> ./environment
# Define log level for the agent.
echo AGENT_LOG_LEVEL=debug >> ./environment
cd ..
KERNEL=<path to kernel built with HAL>
INITRD=<path to initial RAM file system built with HAL>
APPEND="earlyprintk=serial console=ttyS0"
IGVM=<path to IGVM file>
QEMU_BIN=<path to QEMU binary>
ENV_PATH=./env
CERTH_PATH=./certs
$QEMU_BIN -enable-kvm \
-enable-kvm \
-cpu EPYC-v4 \
-machine q35 \
-smp 4,maxcpus=16 \
-m 8G,slots=5,maxmem=30G \
-netdev user,id=vmnic,hostfwd=tcp::7020-:7002 \
-device virtio-net-pci,disable-legacy=on,iommu_platform=true,netdev=vmnic,romfile= \
-machine confidential-guest-support=sev0,memory-backend=ram1,igvm-cfg=igvm0 \
-object memory-backend-memfd,id=ram1,size=8G,share=true,prealloc=false,reserve=false \
-object sev-snp-guest,id=sev0,cbitpos=51,reduced-phys-bits=1 \
-object igvm-cfg,id=igvm0,file=$IGVM \
-initrd $INITRD \
-kernel $KERNEL -append $APPEND \
-nographic \
-monitor pty \
-monitor unix:monitor,server,nowait \
-fsdev local,id=env_fs,path=$ENV_PATH,security_model=mapped \
-device virtio-9p-pci,fsdev=env_fs,mount_tag=env_share \
-fsdev local,id=cert_fs,path=$CERTH_PATH,security_model=mapped \
-device virtio-9p-pci,fsdev=cert_fs,mount_tag=certs_share
```
This command is run from the [manager main directory](../../../cmd/manager/). This will start the manager. Make sure you have already built the [qemu image](../../../hal/linux/README.md).
Make sure you have already built the [qemu image](../../../hal/linux/README.md) and the IGVM file from the COCONUT-SVSM [repository](https://github.com/coconut-svsm/svsm/blob/main/Documentation/docs/installation/INSTALL.md).
In another window, specify what kind of algorithm you want the Agent to run (docker):