mirror of
https://github.com/ultravioletrs/cocos.git
synced 2026-06-23 04:10:25 +00:00
COCOS-394 Cloud Provider Attestation Service Integration (#421)
* Add token measurement command Add Azure cloud attestation fetching Add ability to fetch azure attestation token Remove gcp changes Remove gcp changes Add Azure attestation support Modify pipeline proto checks Update protoc version Fix failing CI fetch token as a file Convert jwt to json Small bug fix -- correct file name for attestation token Fix failing CI Modify protoc version Update protoc version Update protoc version Update protoc version Add changes to allow passing vtpm nonce Add PR review changes to refactor the code Refactor name change to AttestationResult Refactor name change to AttestationResult Return report as json Format files properly Fix attestaton changes Modify changes based on PR review Add more test coverage Correct bug in Server test Rename "FetchAttestationResult" to "AttestationResult" Send token as part of stream Fix CI NOISSUE - Add DisconnectReq message and TTL support for VM creation (#428) * feat: Add DisconnectReq message and TTL support for VM creation - Introduced DisconnectReq message in cvms.proto to handle disconnection requests. - Enhanced CreateReq in manager.proto to include a TTL field for virtual machines. - Updated CLI to accept TTL as a command-line flag during VM creation. - Modified manager service to remove VMs after the specified TTL duration. - Adjusted gRPC client connection handling in agent main.go to support new client structure. - Added mock implementation for gRPC client to facilitate testing. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * fix: Mark server URL flag as required with error handling Signed-off-by: Sammy Oina <sammyoina@gmail.com> --------- Signed-off-by: Sammy Oina <sammyoina@gmail.com> COCOS-407 - Add support for Linux IMA (#429) * Added a feature which enables users to fetch IMA measurements and verify them * Added a feature which enables users to fetch IMA measurements and verify them * fixed lint error * fixed according to comments * fixed according to comments * fixed according to comments * fixed according to comments * final bug fix Add token measurement command Add Azure cloud attestation fetching Add ability to fetch azure attestation token Remove gcp changes Remove gcp changes Add Azure attestation support Modify pipeline proto checks Update protoc version Fix failing CI fetch token as a file Convert jwt to json Small bug fix -- correct file name for attestation token Fix failing CI Modify protoc version Update protoc version Update protoc version Update protoc version Add changes to allow passing vtpm nonce Add PR review changes to refactor the code Refactor name change to AttestationResult Refactor name change to AttestationResult Return report as json Format files properly Fix attestaton changes Modify changes based on PR review Add more test coverage Correct bug in Server test Rename "FetchAttestationResult" to "AttestationResult" Send token as part of stream Fix CI Rebase changes to main Refactor after rebase * Add Azure attestation * COCOS-395 - Cloud Provider Firmware Integration (#415) * add CC platform identification capability * add token verification * add snp azure * add azure snp report verification * fix linter errors * fix agent tests * expand the CC provider * fix azure atls * rebase branch * add nonce check for azure token * rename package attestations * remove alias attestations --------- Co-authored-by: Ubuntu <azureuser@UVCTestCVM.bu0p0zdolasezg1jifpyqhaxuc.dx.internal.cloudapp.net> * Add token measurement command Add Azure cloud attestation fetching Add ability to fetch azure attestation token Remove gcp changes Remove gcp changes Add Azure attestation support Modify pipeline proto checks Update protoc version Fix failing CI fetch token as a file Convert jwt to json Small bug fix -- correct file name for attestation token Fix failing CI Modify protoc version Update protoc version Update protoc version Update protoc version Add changes to allow passing vtpm nonce Add PR review changes to refactor the code Refactor name change to AttestationResult Refactor name change to AttestationResult Return report as json Format files properly Fix attestaton changes Modify changes based on PR review Add more test coverage Correct bug in Server test Rename "FetchAttestationResult" to "AttestationResult" Send token as part of stream Fix CI NOISSUE - Add DisconnectReq message and TTL support for VM creation (#428) * feat: Add DisconnectReq message and TTL support for VM creation - Introduced DisconnectReq message in cvms.proto to handle disconnection requests. - Enhanced CreateReq in manager.proto to include a TTL field for virtual machines. - Updated CLI to accept TTL as a command-line flag during VM creation. - Modified manager service to remove VMs after the specified TTL duration. - Adjusted gRPC client connection handling in agent main.go to support new client structure. - Added mock implementation for gRPC client to facilitate testing. Signed-off-by: Sammy Oina <sammyoina@gmail.com> * fix: Mark server URL flag as required with error handling Signed-off-by: Sammy Oina <sammyoina@gmail.com> --------- Signed-off-by: Sammy Oina <sammyoina@gmail.com> COCOS-407 - Add support for Linux IMA (#429) * Added a feature which enables users to fetch IMA measurements and verify them * Added a feature which enables users to fetch IMA measurements and verify them * fixed lint error * fixed according to comments * fixed according to comments * fixed according to comments * fixed according to comments * final bug fix Add token measurement command Add Azure cloud attestation fetching Add ability to fetch azure attestation token Remove gcp changes Remove gcp changes Add Azure attestation support Modify pipeline proto checks Update protoc version Fix failing CI fetch token as a file Convert jwt to json Small bug fix -- correct file name for attestation token Fix failing CI Modify protoc version Update protoc version Update protoc version Update protoc version Add changes to allow passing vtpm nonce Add PR review changes to refactor the code Refactor name change to AttestationResult Refactor name change to AttestationResult Return report as json Format files properly Fix attestaton changes Modify changes based on PR review Add more test coverage Correct bug in Server test Rename "FetchAttestationResult" to "AttestationResult" Send token as part of stream Fix CI Rebase changes to main Refactor after rebase * Rebase with main * Modify tests to accomodate changes * Use env vars appropriately * Use env vars appropriately * Use caps in err name --------- Co-authored-by: Danko Miladinovic <72250944+danko-miladinovic@users.noreply.github.com> Co-authored-by: Ubuntu <azureuser@UVCTestCVM.bu0p0zdolasezg1jifpyqhaxuc.dx.internal.cloudapp.net>
This commit is contained in:
@@ -9,6 +9,7 @@ on:
|
||||
- "pkg/manager/*.pb.go"
|
||||
- "agent/agent.proto"
|
||||
- "agent/*.pb.go"
|
||||
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
+163
-49
@@ -472,6 +472,102 @@ func (x *IMAMeasurementsResponse) GetPcr10() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
type AttestationResultRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
TokenNonce []byte `protobuf:"bytes,1,opt,name=tokenNonce,proto3" json:"tokenNonce,omitempty"` // Should be less or equal 32 bytes
|
||||
Type int32 `protobuf:"varint,3,opt,name=type,proto3" json:"type,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *AttestationResultRequest) Reset() {
|
||||
*x = AttestationResultRequest{}
|
||||
mi := &file_agent_agent_proto_msgTypes[10]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *AttestationResultRequest) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*AttestationResultRequest) ProtoMessage() {}
|
||||
|
||||
func (x *AttestationResultRequest) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_agent_agent_proto_msgTypes[10]
|
||||
if x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use AttestationResultRequest.ProtoReflect.Descriptor instead.
|
||||
func (*AttestationResultRequest) Descriptor() ([]byte, []int) {
|
||||
return file_agent_agent_proto_rawDescGZIP(), []int{10}
|
||||
}
|
||||
|
||||
func (x *AttestationResultRequest) GetTokenNonce() []byte {
|
||||
if x != nil {
|
||||
return x.TokenNonce
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *AttestationResultRequest) GetType() int32 {
|
||||
if x != nil {
|
||||
return x.Type
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
type AttestationResultResponse struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
File []byte `protobuf:"bytes,1,opt,name=file,proto3" json:"file,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
||||
func (x *AttestationResultResponse) Reset() {
|
||||
*x = AttestationResultResponse{}
|
||||
mi := &file_agent_agent_proto_msgTypes[11]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *AttestationResultResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*AttestationResultResponse) ProtoMessage() {}
|
||||
|
||||
func (x *AttestationResultResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_agent_agent_proto_msgTypes[11]
|
||||
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 AttestationResultResponse.ProtoReflect.Descriptor instead.
|
||||
func (*AttestationResultResponse) Descriptor() ([]byte, []int) {
|
||||
return file_agent_agent_proto_rawDescGZIP(), []int{11}
|
||||
}
|
||||
|
||||
func (x *AttestationResultResponse) GetFile() []byte {
|
||||
if x != nil {
|
||||
return x.File
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_agent_agent_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_agent_agent_proto_rawDesc = string([]byte{
|
||||
@@ -506,29 +602,43 @@ var file_agent_agent_proto_rawDesc = string([]byte{
|
||||
0x6e, 0x74, 0x73, 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,
|
||||
0x14, 0x0a, 0x05, 0x70, 0x63, 0x72, 0x31, 0x30, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05,
|
||||
0x70, 0x63, 0x72, 0x31, 0x30, 0x32, 0xd3, 0x02, 0x0a, 0x0c, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x53,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x04, 0x41, 0x6c, 0x67, 0x6f, 0x12, 0x12,
|
||||
0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x6c, 0x67, 0x6f, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x6c, 0x67, 0x6f, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x12, 0x33, 0x0a, 0x04, 0x44,
|
||||
0x61, 0x74, 0x61, 0x12, 0x12, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e,
|
||||
0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01,
|
||||
0x12, 0x39, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x14, 0x2e, 0x61, 0x67, 0x65,
|
||||
0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x15, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x48, 0x0a, 0x0b, 0x41,
|
||||
0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x61, 0x67, 0x65,
|
||||
0x6e, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65,
|
||||
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x74,
|
||||
0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x54, 0x0a, 0x0f, 0x49, 0x4d, 0x41, 0x4d, 0x65, 0x61, 0x73,
|
||||
0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1d, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74,
|
||||
0x70, 0x63, 0x72, 0x31, 0x30, 0x22, 0x4e, 0x0a, 0x18, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x12, 0x1e, 0x0a, 0x0a, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x4e, 0x6f, 0x6e, 0x63, 0x65, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x4e, 0x6f, 0x6e, 0x63,
|
||||
0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52,
|
||||
0x04, 0x74, 0x79, 0x70, 0x65, 0x22, 0x2f, 0x0a, 0x19, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 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, 0x32, 0xad, 0x03, 0x0a, 0x0c, 0x41, 0x67, 0x65, 0x6e, 0x74,
|
||||
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x33, 0x0a, 0x04, 0x41, 0x6c, 0x67, 0x6f, 0x12,
|
||||
0x12, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x6c, 0x67, 0x6f, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x6c, 0x67, 0x6f,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28, 0x01, 0x12, 0x33, 0x0a, 0x04,
|
||||
0x44, 0x61, 0x74, 0x61, 0x12, 0x12, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x44, 0x61, 0x74,
|
||||
0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74,
|
||||
0x2e, 0x44, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x28,
|
||||
0x01, 0x12, 0x39, 0x0a, 0x06, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x12, 0x14, 0x2e, 0x61, 0x67,
|
||||
0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
|
||||
0x74, 0x1a, 0x15, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x48, 0x0a, 0x0b,
|
||||
0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x2e, 0x61, 0x67,
|
||||
0x65, 0x6e, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41,
|
||||
0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x54, 0x0a, 0x0f, 0x49, 0x4d, 0x41, 0x4d, 0x65, 0x61,
|
||||
0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1d, 0x2e, 0x61, 0x67, 0x65, 0x6e,
|
||||
0x74, 0x2e, 0x49, 0x4d, 0x41, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74,
|
||||
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74,
|
||||
0x2e, 0x49, 0x4d, 0x41, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73,
|
||||
0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e,
|
||||
0x49, 0x4d, 0x41, 0x4d, 0x65, 0x61, 0x73, 0x75, 0x72, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x42, 0x09, 0x5a, 0x07, 0x2e,
|
||||
0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x58, 0x0a, 0x11,
|
||||
0x41, 0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c,
|
||||
0x74, 0x12, 0x1f, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73, 0x74,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x20, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x73,
|
||||
0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x52, 0x65, 0x73, 0x70,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x09, 0x5a, 0x07, 0x2e, 0x2f, 0x61, 0x67, 0x65, 0x6e,
|
||||
0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
})
|
||||
|
||||
var (
|
||||
@@ -543,35 +653,39 @@ func file_agent_agent_proto_rawDescGZIP() []byte {
|
||||
return file_agent_agent_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_agent_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 10)
|
||||
var file_agent_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 12)
|
||||
var file_agent_agent_proto_goTypes = []any{
|
||||
(*AlgoRequest)(nil), // 0: agent.AlgoRequest
|
||||
(*AlgoResponse)(nil), // 1: agent.AlgoResponse
|
||||
(*DataRequest)(nil), // 2: agent.DataRequest
|
||||
(*DataResponse)(nil), // 3: agent.DataResponse
|
||||
(*ResultRequest)(nil), // 4: agent.ResultRequest
|
||||
(*ResultResponse)(nil), // 5: agent.ResultResponse
|
||||
(*AttestationRequest)(nil), // 6: agent.AttestationRequest
|
||||
(*AttestationResponse)(nil), // 7: agent.AttestationResponse
|
||||
(*IMAMeasurementsRequest)(nil), // 8: agent.IMAMeasurementsRequest
|
||||
(*IMAMeasurementsResponse)(nil), // 9: agent.IMAMeasurementsResponse
|
||||
(*AlgoRequest)(nil), // 0: agent.AlgoRequest
|
||||
(*AlgoResponse)(nil), // 1: agent.AlgoResponse
|
||||
(*DataRequest)(nil), // 2: agent.DataRequest
|
||||
(*DataResponse)(nil), // 3: agent.DataResponse
|
||||
(*ResultRequest)(nil), // 4: agent.ResultRequest
|
||||
(*ResultResponse)(nil), // 5: agent.ResultResponse
|
||||
(*AttestationRequest)(nil), // 6: agent.AttestationRequest
|
||||
(*AttestationResponse)(nil), // 7: agent.AttestationResponse
|
||||
(*IMAMeasurementsRequest)(nil), // 8: agent.IMAMeasurementsRequest
|
||||
(*IMAMeasurementsResponse)(nil), // 9: agent.IMAMeasurementsResponse
|
||||
(*AttestationResultRequest)(nil), // 10: agent.AttestationResultRequest
|
||||
(*AttestationResultResponse)(nil), // 11: agent.AttestationResultResponse
|
||||
}
|
||||
var file_agent_agent_proto_depIdxs = []int32{
|
||||
0, // 0: agent.AgentService.Algo:input_type -> agent.AlgoRequest
|
||||
2, // 1: agent.AgentService.Data:input_type -> agent.DataRequest
|
||||
4, // 2: agent.AgentService.Result:input_type -> agent.ResultRequest
|
||||
6, // 3: agent.AgentService.Attestation:input_type -> agent.AttestationRequest
|
||||
8, // 4: agent.AgentService.IMAMeasurements:input_type -> agent.IMAMeasurementsRequest
|
||||
1, // 5: agent.AgentService.Algo:output_type -> agent.AlgoResponse
|
||||
3, // 6: agent.AgentService.Data:output_type -> agent.DataResponse
|
||||
5, // 7: agent.AgentService.Result:output_type -> agent.ResultResponse
|
||||
7, // 8: agent.AgentService.Attestation:output_type -> agent.AttestationResponse
|
||||
9, // 9: agent.AgentService.IMAMeasurements:output_type -> agent.IMAMeasurementsResponse
|
||||
5, // [5:10] is the sub-list for method output_type
|
||||
0, // [0:5] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
0, // 0: agent.AgentService.Algo:input_type -> agent.AlgoRequest
|
||||
2, // 1: agent.AgentService.Data:input_type -> agent.DataRequest
|
||||
4, // 2: agent.AgentService.Result:input_type -> agent.ResultRequest
|
||||
6, // 3: agent.AgentService.Attestation:input_type -> agent.AttestationRequest
|
||||
8, // 4: agent.AgentService.IMAMeasurements:input_type -> agent.IMAMeasurementsRequest
|
||||
10, // 5: agent.AgentService.AttestationResult:input_type -> agent.AttestationResultRequest
|
||||
1, // 6: agent.AgentService.Algo:output_type -> agent.AlgoResponse
|
||||
3, // 7: agent.AgentService.Data:output_type -> agent.DataResponse
|
||||
5, // 8: agent.AgentService.Result:output_type -> agent.ResultResponse
|
||||
7, // 9: agent.AgentService.Attestation:output_type -> agent.AttestationResponse
|
||||
9, // 10: agent.AgentService.IMAMeasurements:output_type -> agent.IMAMeasurementsResponse
|
||||
11, // 11: agent.AgentService.AttestationResult:output_type -> agent.AttestationResultResponse
|
||||
6, // [6:12] is the sub-list for method output_type
|
||||
0, // [0:6] is the sub-list for method input_type
|
||||
0, // [0:0] is the sub-list for extension type_name
|
||||
0, // [0:0] is the sub-list for extension extendee
|
||||
0, // [0:0] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_agent_agent_proto_init() }
|
||||
@@ -585,7 +699,7 @@ func file_agent_agent_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_agent_agent_proto_rawDesc), len(file_agent_agent_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 10,
|
||||
NumMessages: 12,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
||||
@@ -13,6 +13,7 @@ service AgentService {
|
||||
rpc Result(ResultRequest) returns (stream ResultResponse) {}
|
||||
rpc Attestation(AttestationRequest) returns (stream AttestationResponse) {}
|
||||
rpc IMAMeasurements(IMAMeasurementsRequest) returns (stream IMAMeasurementsResponse) {}
|
||||
rpc AttestationResult(AttestationResultRequest) returns (AttestationResultResponse) {}
|
||||
}
|
||||
|
||||
message AlgoRequest {
|
||||
@@ -53,3 +54,11 @@ message IMAMeasurementsResponse {
|
||||
bytes file = 1;
|
||||
bytes pcr10 = 2;
|
||||
}
|
||||
|
||||
message AttestationResultRequest{
|
||||
bytes tokenNonce = 1; // Should be less or equal 32 bytes
|
||||
int32 type = 3;
|
||||
}
|
||||
message AttestationResultResponse{
|
||||
bytes file = 1;
|
||||
}
|
||||
|
||||
+45
-6
@@ -22,11 +22,12 @@ import (
|
||||
const _ = grpc.SupportPackageIsVersion9
|
||||
|
||||
const (
|
||||
AgentService_Algo_FullMethodName = "/agent.AgentService/Algo"
|
||||
AgentService_Data_FullMethodName = "/agent.AgentService/Data"
|
||||
AgentService_Result_FullMethodName = "/agent.AgentService/Result"
|
||||
AgentService_Attestation_FullMethodName = "/agent.AgentService/Attestation"
|
||||
AgentService_IMAMeasurements_FullMethodName = "/agent.AgentService/IMAMeasurements"
|
||||
AgentService_Algo_FullMethodName = "/agent.AgentService/Algo"
|
||||
AgentService_Data_FullMethodName = "/agent.AgentService/Data"
|
||||
AgentService_Result_FullMethodName = "/agent.AgentService/Result"
|
||||
AgentService_Attestation_FullMethodName = "/agent.AgentService/Attestation"
|
||||
AgentService_IMAMeasurements_FullMethodName = "/agent.AgentService/IMAMeasurements"
|
||||
AgentService_AttestationResult_FullMethodName = "/agent.AgentService/AttestationResult"
|
||||
)
|
||||
|
||||
// AgentServiceClient is the client API for AgentService service.
|
||||
@@ -38,6 +39,7 @@ type AgentServiceClient interface {
|
||||
Result(ctx context.Context, in *ResultRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[ResultResponse], error)
|
||||
Attestation(ctx context.Context, in *AttestationRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[AttestationResponse], error)
|
||||
IMAMeasurements(ctx context.Context, in *IMAMeasurementsRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[IMAMeasurementsResponse], error)
|
||||
AttestationResult(ctx context.Context, in *AttestationResultRequest, opts ...grpc.CallOption) (*AttestationResultResponse, error)
|
||||
}
|
||||
|
||||
type agentServiceClient struct {
|
||||
@@ -131,6 +133,16 @@ func (c *agentServiceClient) IMAMeasurements(ctx context.Context, in *IMAMeasure
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type AgentService_IMAMeasurementsClient = grpc.ServerStreamingClient[IMAMeasurementsResponse]
|
||||
|
||||
func (c *agentServiceClient) AttestationResult(ctx context.Context, in *AttestationResultRequest, opts ...grpc.CallOption) (*AttestationResultResponse, error) {
|
||||
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
|
||||
out := new(AttestationResultResponse)
|
||||
err := c.cc.Invoke(ctx, AgentService_AttestationResult_FullMethodName, in, out, cOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// AgentServiceServer is the server API for AgentService service.
|
||||
// All implementations must embed UnimplementedAgentServiceServer
|
||||
// for forward compatibility.
|
||||
@@ -140,6 +152,7 @@ type AgentServiceServer interface {
|
||||
Result(*ResultRequest, grpc.ServerStreamingServer[ResultResponse]) error
|
||||
Attestation(*AttestationRequest, grpc.ServerStreamingServer[AttestationResponse]) error
|
||||
IMAMeasurements(*IMAMeasurementsRequest, grpc.ServerStreamingServer[IMAMeasurementsResponse]) error
|
||||
AttestationResult(context.Context, *AttestationResultRequest) (*AttestationResultResponse, error)
|
||||
mustEmbedUnimplementedAgentServiceServer()
|
||||
}
|
||||
|
||||
@@ -165,6 +178,9 @@ func (UnimplementedAgentServiceServer) Attestation(*AttestationRequest, grpc.Ser
|
||||
func (UnimplementedAgentServiceServer) IMAMeasurements(*IMAMeasurementsRequest, grpc.ServerStreamingServer[IMAMeasurementsResponse]) error {
|
||||
return status.Errorf(codes.Unimplemented, "method IMAMeasurements not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServiceServer) AttestationResult(context.Context, *AttestationResultRequest) (*AttestationResultResponse, error) {
|
||||
return nil, status.Errorf(codes.Unimplemented, "method AttestationResult not implemented")
|
||||
}
|
||||
func (UnimplementedAgentServiceServer) mustEmbedUnimplementedAgentServiceServer() {}
|
||||
func (UnimplementedAgentServiceServer) testEmbeddedByValue() {}
|
||||
|
||||
@@ -233,13 +249,36 @@ func _AgentService_IMAMeasurements_Handler(srv interface{}, stream grpc.ServerSt
|
||||
// This type alias is provided for backwards compatibility with existing code that references the prior non-generic stream type by name.
|
||||
type AgentService_IMAMeasurementsServer = grpc.ServerStreamingServer[IMAMeasurementsResponse]
|
||||
|
||||
func _AgentService_AttestationResult_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||
in := new(AttestationResultRequest)
|
||||
if err := dec(in); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if interceptor == nil {
|
||||
return srv.(AgentServiceServer).AttestationResult(ctx, in)
|
||||
}
|
||||
info := &grpc.UnaryServerInfo{
|
||||
Server: srv,
|
||||
FullMethod: AgentService_AttestationResult_FullMethodName,
|
||||
}
|
||||
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
|
||||
return srv.(AgentServiceServer).AttestationResult(ctx, req.(*AttestationResultRequest))
|
||||
}
|
||||
return interceptor(ctx, in, info, handler)
|
||||
}
|
||||
|
||||
// AgentService_ServiceDesc is the grpc.ServiceDesc for AgentService service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var AgentService_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "agent.AgentService",
|
||||
HandlerType: (*AgentServiceServer)(nil),
|
||||
Methods: []grpc.MethodDesc{},
|
||||
Methods: []grpc.MethodDesc{
|
||||
{
|
||||
MethodName: "AttestationResult",
|
||||
Handler: _AgentService_AttestationResult_Handler,
|
||||
},
|
||||
},
|
||||
Streams: []grpc.StreamDesc{
|
||||
{
|
||||
StreamName: "Algo",
|
||||
|
||||
@@ -95,3 +95,17 @@ func imaMeasurementsEndpoint(svc agent.Service) endpoint.Endpoint {
|
||||
return imaMeasurementsRes{File: file, PCR10: pcr10}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func attestationResultEndpoint(svc agent.Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (interface{}, error) {
|
||||
req := request.(FetchAttestationResultReq)
|
||||
if err := req.validate(); err != nil {
|
||||
return fetchAttestationResultRes{}, err
|
||||
}
|
||||
file, err := svc.AttestationResult(ctx, req.tokenNonce, attestation.PlatformType(req.AttType))
|
||||
if err != nil {
|
||||
return fetchAttestationResultRes{}, err
|
||||
}
|
||||
return fetchAttestationResultRes{File: file}, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/mock"
|
||||
"github.com/ultravioletrs/cocos/agent"
|
||||
"github.com/ultravioletrs/cocos/agent/mocks"
|
||||
"github.com/ultravioletrs/cocos/pkg/attestation"
|
||||
@@ -172,3 +173,55 @@ func TestAttestationEndpoint(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAttestationResultEndpoint(t *testing.T) {
|
||||
svc := new(mocks.Service)
|
||||
tests := []struct {
|
||||
name string
|
||||
req FetchAttestationResultReq
|
||||
mockErr error
|
||||
expectedErr bool
|
||||
}{
|
||||
{
|
||||
name: "Success",
|
||||
req: FetchAttestationResultReq{tokenNonce: sha3.Sum256([]byte("vtpm nonce")), AttType: attestation.AzureToken},
|
||||
mockErr: nil,
|
||||
expectedErr: false,
|
||||
},
|
||||
{
|
||||
name: "Service Error",
|
||||
req: FetchAttestationResultReq{tokenNonce: sha3.Sum256([]byte("vtpm nonce")), AttType: attestation.AzureToken},
|
||||
mockErr: errors.New("mock failure"),
|
||||
expectedErr: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Only call service mock if validation is expected to pass
|
||||
if err := tt.req.validate(); err == nil {
|
||||
svc.On("AttestationResult", mock.Anything, tt.req.tokenNonce, attestation.PlatformType(tt.req.AttType)).
|
||||
Return([]byte("mock file"), tt.mockErr).Once()
|
||||
}
|
||||
|
||||
endpoint := attestationResultEndpoint(svc)
|
||||
res, err := endpoint(context.Background(), tt.req)
|
||||
|
||||
if (err != nil) != tt.expectedErr {
|
||||
t.Errorf("attestationResultEndpoint() error = %v, expectedErr %v", err, tt.expectedErr)
|
||||
}
|
||||
|
||||
if !tt.expectedErr {
|
||||
r, ok := res.(fetchAttestationResultRes)
|
||||
if !ok {
|
||||
t.Errorf("attestationResultEndpoint() returned unexpected type %T", res)
|
||||
}
|
||||
if string(r.File) != "mock file" {
|
||||
t.Errorf("expected file content 'mock file', got %s", r.File)
|
||||
}
|
||||
}
|
||||
|
||||
svc.AssertExpectations(t)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,12 +47,25 @@ type attestationReq struct {
|
||||
AttType attestation.PlatformType
|
||||
}
|
||||
|
||||
type FetchAttestationResultReq struct {
|
||||
tokenNonce [vtpm.Nonce]byte
|
||||
AttType attestation.PlatformType
|
||||
}
|
||||
|
||||
func (req attestationReq) validate() error {
|
||||
switch req.AttType {
|
||||
case attestation.SNP, attestation.VTPM, attestation.SNPvTPM:
|
||||
return validateAttestationType(req.AttType)
|
||||
}
|
||||
|
||||
func (req FetchAttestationResultReq) validate() error {
|
||||
return validateAttestationType(req.AttType)
|
||||
}
|
||||
|
||||
func validateAttestationType(attType attestation.PlatformType) error {
|
||||
switch attType {
|
||||
case attestation.SNP, attestation.VTPM, attestation.SNPvTPM, attestation.AzureToken:
|
||||
return nil
|
||||
default:
|
||||
return errors.New("invalid attestation type in attestation request")
|
||||
return errors.New("invalid attestation type")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,3 +18,7 @@ type imaMeasurementsRes struct {
|
||||
File []byte
|
||||
PCR10 []byte
|
||||
}
|
||||
|
||||
type fetchAttestationResultRes struct {
|
||||
File []byte `protobuf:"bytes,1,opt,name=AttestationResult,proto3" json:"AttestationResult,omitempty"`
|
||||
}
|
||||
|
||||
@@ -26,18 +26,20 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
ErrTEENonceLength = errors.New("malformed report data, expect less or equal to 64 bytes")
|
||||
ErrVTpmNonceLength = errors.New("malformed vTPM nonce, expect less or equal to 32 bytes")
|
||||
ErrTEENonceLength = errors.New("malformed report data, expect less or equal to 64 bytes")
|
||||
ErrVTPMNonceLength = errors.New("malformed vTPM nonce, expect less or equal to 32 bytes")
|
||||
ErrTokenNonceLength = errors.New("malformed token nonce, expect less or equal to 32 bytes")
|
||||
)
|
||||
|
||||
var _ agent.AgentServiceServer = (*grpcServer)(nil)
|
||||
|
||||
type grpcServer struct {
|
||||
algo grpc.Handler
|
||||
data grpc.Handler
|
||||
result grpc.Handler
|
||||
attestation grpc.Handler
|
||||
imaMeasurements grpc.Handler
|
||||
algo grpc.Handler
|
||||
data grpc.Handler
|
||||
result grpc.Handler
|
||||
attestation grpc.Handler
|
||||
imaMeasurements grpc.Handler
|
||||
attestationResult grpc.Handler
|
||||
agent.UnimplementedAgentServiceServer
|
||||
}
|
||||
|
||||
@@ -69,6 +71,11 @@ func NewServer(svc agent.Service) agent.AgentServiceServer {
|
||||
decodeIMAMeasurementsRequest,
|
||||
encodeIMAMeasurementsResponse,
|
||||
),
|
||||
attestationResult: grpc.NewServer(
|
||||
attestationResultEndpoint(svc),
|
||||
decodeAttestationResultRequest,
|
||||
encodeAttestationResultResponse,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +126,7 @@ func decodeAttestationRequest(_ context.Context, grpcReq interface{}) (interface
|
||||
}
|
||||
|
||||
if len(req.VtpmNonce) > vtpm.Nonce {
|
||||
return nil, ErrVTpmNonceLength
|
||||
return nil, ErrVTPMNonceLength
|
||||
}
|
||||
|
||||
copy(reportData[:], req.TeeNonce)
|
||||
@@ -134,6 +141,25 @@ func encodeAttestationResponse(_ context.Context, response interface{}) (interfa
|
||||
}, nil
|
||||
}
|
||||
|
||||
func encodeAttestationResultResponse(_ context.Context, response interface{}) (interface{}, error) {
|
||||
res := response.(fetchAttestationResultRes)
|
||||
return &agent.AttestationResultResponse{
|
||||
File: res.File,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func decodeAttestationResultRequest(_ context.Context, grpcReq interface{}) (interface{}, error) {
|
||||
req := grpcReq.(*agent.AttestationResultRequest)
|
||||
var nonce [vtpm.Nonce]byte
|
||||
|
||||
if len(req.TokenNonce) > vtpm.Nonce {
|
||||
return nil, ErrVTPMNonceLength
|
||||
}
|
||||
|
||||
copy(nonce[:], req.TokenNonce)
|
||||
return FetchAttestationResultReq{tokenNonce: nonce, AttType: attestation.PlatformType(req.Type)}, nil
|
||||
}
|
||||
|
||||
// Algo implements agent.AgentServiceServer.
|
||||
func (s *grpcServer) Algo(stream agent.AgentService_AlgoServer) error {
|
||||
var algoFile, reqFile []byte
|
||||
@@ -295,3 +321,17 @@ func (s *grpcServer) IMAMeasurements(req *agent.IMAMeasurementsRequest, stream a
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *grpcServer) AttestationResult(ctx context.Context, req *agent.AttestationResultRequest) (*agent.AttestationResultResponse, error) {
|
||||
_, res, err := s.attestationResult.ServeGRPC(ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rr, ok := res.(*agent.AttestationResultResponse)
|
||||
|
||||
if !ok {
|
||||
return nil, status.Error(codes.Internal, "failed to cast response to FetchAttestationResultResponse")
|
||||
}
|
||||
|
||||
return rr, nil
|
||||
}
|
||||
|
||||
@@ -165,6 +165,21 @@ func TestAttestation(t *testing.T) {
|
||||
mockService.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestAttestationResult(t *testing.T) {
|
||||
mockService := new(mocks.Service)
|
||||
server := NewServer(mockService)
|
||||
|
||||
vtpmNonce := [vtpm.Nonce]byte{}
|
||||
attestationType := attestation.SNP
|
||||
mockService.On("AttestationResult", mock.Anything, vtpmNonce, attestationType).Return([]byte("attestation data"), nil)
|
||||
|
||||
resp, err := server.AttestationResult(context.Background(), &agent.AttestationResultRequest{TokenNonce: vtpmNonce[:]})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("attestation data"), resp.File)
|
||||
|
||||
mockService.AssertExpectations(t)
|
||||
}
|
||||
|
||||
func TestDecodeAlgoRequest(t *testing.T) {
|
||||
req := &agent.AlgoRequest{Algorithm: []byte("algo"), Requirements: []byte("req")}
|
||||
decoded, err := decodeAlgoRequest(context.Background(), req)
|
||||
@@ -216,3 +231,17 @@ func TestEncodeAttestationResponse(t *testing.T) {
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, &agent.AttestationResponse{File: []byte("attestation")}, encoded)
|
||||
}
|
||||
|
||||
func TestEncodeAttestationResultResponse(t *testing.T) {
|
||||
encoded, err := encodeAttestationResultResponse(context.Background(), fetchAttestationResultRes{File: []byte("attestation")})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, &agent.AttestationResultResponse{File: []byte("attestation")}, encoded)
|
||||
}
|
||||
|
||||
func TestDecodeAttestationResultRequest(t *testing.T) {
|
||||
nonce := [vtpm.Nonce]byte{}
|
||||
req := &agent.AttestationResultRequest{TokenNonce: nonce[:]}
|
||||
decoded, err := decodeAttestationResultRequest(context.Background(), req)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, FetchAttestationResultReq{tokenNonce: nonce}, decoded)
|
||||
}
|
||||
|
||||
@@ -131,3 +131,16 @@ func (lm *loggingMiddleware) IMAMeasurements(ctx context.Context) (file []byte,
|
||||
|
||||
return lm.svc.IMAMeasurements(ctx)
|
||||
}
|
||||
|
||||
func (lm *loggingMiddleware) AttestationResult(ctx context.Context, nonce [vtpm.Nonce]byte, attType attestation.PlatformType) (response []byte, err error) {
|
||||
defer func(begin time.Time) {
|
||||
message := fmt.Sprintf("Method Attestation took %s to complete", time.Since(begin))
|
||||
if err != nil {
|
||||
lm.logger.Warn(fmt.Sprintf("%s with error: %s", message, err))
|
||||
return
|
||||
}
|
||||
lm.logger.Info(fmt.Sprintf("%s without errors", message))
|
||||
}(time.Now())
|
||||
|
||||
return lm.svc.AttestationResult(ctx, nonce, attType)
|
||||
}
|
||||
|
||||
@@ -101,6 +101,15 @@ func (ms *metricsMiddleware) Attestation(ctx context.Context, reportData [quotep
|
||||
return ms.svc.Attestation(ctx, reportData, nonce, attType)
|
||||
}
|
||||
|
||||
func (ms *metricsMiddleware) AttestationResult(ctx context.Context, nonce [vtpm.Nonce]byte, attType attestation.PlatformType) ([]byte, error) {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "attestation_result").Add(1)
|
||||
ms.latency.With("method", "attestation_result").Observe(time.Since(begin).Seconds())
|
||||
}(time.Now())
|
||||
|
||||
return ms.svc.AttestationResult(ctx, nonce, attType)
|
||||
}
|
||||
|
||||
func (ms *metricsMiddleware) IMAMeasurements(ctx context.Context) ([]byte, []byte, error) {
|
||||
defer func(begin time.Time) {
|
||||
ms.counter.With("method", "imameasurements").Add(1)
|
||||
|
||||
+207
-125
@@ -431,6 +431,7 @@ type ClientStreamMessage struct {
|
||||
// *ClientStreamMessage_StopComputationRes
|
||||
// *ClientStreamMessage_AgentStateRes
|
||||
// *ClientStreamMessage_VTPMattestationReport
|
||||
// *ClientStreamMessage_AzureAttestationResult
|
||||
Message isClientStreamMessage_Message `protobuf_oneof:"message"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -527,6 +528,15 @@ func (x *ClientStreamMessage) GetVTPMattestationReport() *AttestationResponse {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ClientStreamMessage) GetAzureAttestationResult() *AzureAttestationResponse {
|
||||
if x != nil {
|
||||
if x, ok := x.Message.(*ClientStreamMessage_AzureAttestationResult); ok {
|
||||
return x.AzureAttestationResult
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type isClientStreamMessage_Message interface {
|
||||
isClientStreamMessage_Message()
|
||||
}
|
||||
@@ -555,6 +565,10 @@ type ClientStreamMessage_VTPMattestationReport struct {
|
||||
VTPMattestationReport *AttestationResponse `protobuf:"bytes,6,opt,name=vTPMattestationReport,proto3,oneof"`
|
||||
}
|
||||
|
||||
type ClientStreamMessage_AzureAttestationResult struct {
|
||||
AzureAttestationResult *AzureAttestationResponse `protobuf:"bytes,7,opt,name=azureAttestationResult,proto3,oneof"`
|
||||
}
|
||||
|
||||
func (*ClientStreamMessage_AgentLog) isClientStreamMessage_Message() {}
|
||||
|
||||
func (*ClientStreamMessage_AgentEvent) isClientStreamMessage_Message() {}
|
||||
@@ -567,6 +581,8 @@ func (*ClientStreamMessage_AgentStateRes) isClientStreamMessage_Message() {}
|
||||
|
||||
func (*ClientStreamMessage_VTPMattestationReport) isClientStreamMessage_Message() {}
|
||||
|
||||
func (*ClientStreamMessage_AzureAttestationResult) isClientStreamMessage_Message() {}
|
||||
|
||||
type ServerStreamMessage struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
// Types that are valid to be assigned to Message:
|
||||
@@ -1193,6 +1209,58 @@ func (x *AttestationResponse) GetCertSerialNumber() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
type AzureAttestationResponse 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 *AzureAttestationResponse) Reset() {
|
||||
*x = AzureAttestationResponse{}
|
||||
mi := &file_agent_cvms_cvms_proto_msgTypes[17]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
|
||||
func (x *AzureAttestationResponse) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*AzureAttestationResponse) ProtoMessage() {}
|
||||
|
||||
func (x *AzureAttestationResponse) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_agent_cvms_cvms_proto_msgTypes[17]
|
||||
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 AzureAttestationResponse.ProtoReflect.Descriptor instead.
|
||||
func (*AzureAttestationResponse) Descriptor() ([]byte, []int) {
|
||||
return file_agent_cvms_cvms_proto_rawDescGZIP(), []int{17}
|
||||
}
|
||||
|
||||
func (x *AzureAttestationResponse) GetFile() []byte {
|
||||
if x != nil {
|
||||
return x.File
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *AzureAttestationResponse) GetCertSerialNumber() string {
|
||||
if x != nil {
|
||||
return x.CertSerialNumber
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_agent_cvms_cvms_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_agent_cvms_cvms_proto_rawDesc = string([]byte{
|
||||
@@ -1243,7 +1311,7 @@ var file_agent_cvms_cvms_proto_rawDesc = string([]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, 0x93, 0x03, 0x0a, 0x13, 0x43, 0x6c, 0x69, 0x65,
|
||||
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0xed, 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,
|
||||
@@ -1268,92 +1336,103 @@ var file_agent_cvms_cvms_proto_rawDesc = string([]byte{
|
||||
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, 0xca, 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, 0x12, 0x3b, 0x0a, 0x0d, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74,
|
||||
0x52, 0x65, 0x71, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x76, 0x6d, 0x73,
|
||||
0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x48, 0x00,
|
||||
0x52, 0x0d, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x42,
|
||||
0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x1f, 0x0a, 0x0d, 0x44, 0x69,
|
||||
0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x12, 0x0e, 0x0a, 0x02, 0x69,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 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,
|
||||
0x72, 0x74, 0x12, 0x58, 0x0a, 0x16, 0x61, 0x7a, 0x75, 0x72, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73,
|
||||
0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x18, 0x07, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x63, 0x76, 0x6d, 0x73, 0x2e, 0x61, 0x7a, 0x75, 0x72, 0x65, 0x41,
|
||||
0x74, 0x74, 0x65, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x48, 0x00, 0x52, 0x16, 0x61, 0x7a, 0x75, 0x72, 0x65, 0x41, 0x74, 0x74, 0x65, 0x73,
|
||||
0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x42, 0x09, 0x0a, 0x07,
|
||||
0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0xca, 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, 0x12, 0x3b, 0x0a, 0x0d,
|
||||
0x64, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x18, 0x05, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x63, 0x76, 0x6d, 0x73, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f,
|
||||
0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x48, 0x00, 0x52, 0x0d, 0x64, 0x69, 0x73, 0x63,
|
||||
0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x52, 0x65, 0x71, 0x42, 0x09, 0x0a, 0x07, 0x6d, 0x65, 0x73,
|
||||
0x73, 0x61, 0x67, 0x65, 0x22, 0x1f, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65,
|
||||
0x63, 0x74, 0x52, 0x65, 0x71, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x02, 0x69, 0x64, 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, 0x22, 0x5a, 0x0a, 0x18, 0x61, 0x7a,
|
||||
0x75, 0x72, 0x65, 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 (
|
||||
@@ -1368,52 +1447,54 @@ func file_agent_cvms_cvms_proto_rawDescGZIP() []byte {
|
||||
return file_agent_cvms_cvms_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_agent_cvms_cvms_proto_msgTypes = make([]protoimpl.MessageInfo, 17)
|
||||
var file_agent_cvms_cvms_proto_msgTypes = make([]protoimpl.MessageInfo, 18)
|
||||
var file_agent_cvms_cvms_proto_goTypes = []any{
|
||||
(*AgentStateReq)(nil), // 0: cvms.AgentStateReq
|
||||
(*AgentStateRes)(nil), // 1: cvms.AgentStateRes
|
||||
(*StopComputation)(nil), // 2: cvms.StopComputation
|
||||
(*StopComputationResponse)(nil), // 3: cvms.StopComputationResponse
|
||||
(*RunResponse)(nil), // 4: cvms.RunResponse
|
||||
(*AgentEvent)(nil), // 5: cvms.AgentEvent
|
||||
(*AgentLog)(nil), // 6: cvms.AgentLog
|
||||
(*ClientStreamMessage)(nil), // 7: cvms.ClientStreamMessage
|
||||
(*ServerStreamMessage)(nil), // 8: cvms.ServerStreamMessage
|
||||
(*DisconnectReq)(nil), // 9: cvms.DisconnectReq
|
||||
(*RunReqChunks)(nil), // 10: cvms.RunReqChunks
|
||||
(*ComputationRunReq)(nil), // 11: cvms.ComputationRunReq
|
||||
(*ResultConsumer)(nil), // 12: cvms.ResultConsumer
|
||||
(*Dataset)(nil), // 13: cvms.Dataset
|
||||
(*Algorithm)(nil), // 14: cvms.Algorithm
|
||||
(*AgentConfig)(nil), // 15: cvms.AgentConfig
|
||||
(*AttestationResponse)(nil), // 16: cvms.AttestationResponse
|
||||
(*timestamppb.Timestamp)(nil), // 17: google.protobuf.Timestamp
|
||||
(*AgentStateReq)(nil), // 0: cvms.AgentStateReq
|
||||
(*AgentStateRes)(nil), // 1: cvms.AgentStateRes
|
||||
(*StopComputation)(nil), // 2: cvms.StopComputation
|
||||
(*StopComputationResponse)(nil), // 3: cvms.StopComputationResponse
|
||||
(*RunResponse)(nil), // 4: cvms.RunResponse
|
||||
(*AgentEvent)(nil), // 5: cvms.AgentEvent
|
||||
(*AgentLog)(nil), // 6: cvms.AgentLog
|
||||
(*ClientStreamMessage)(nil), // 7: cvms.ClientStreamMessage
|
||||
(*ServerStreamMessage)(nil), // 8: cvms.ServerStreamMessage
|
||||
(*DisconnectReq)(nil), // 9: cvms.DisconnectReq
|
||||
(*RunReqChunks)(nil), // 10: cvms.RunReqChunks
|
||||
(*ComputationRunReq)(nil), // 11: cvms.ComputationRunReq
|
||||
(*ResultConsumer)(nil), // 12: cvms.ResultConsumer
|
||||
(*Dataset)(nil), // 13: cvms.Dataset
|
||||
(*Algorithm)(nil), // 14: cvms.Algorithm
|
||||
(*AgentConfig)(nil), // 15: cvms.AgentConfig
|
||||
(*AttestationResponse)(nil), // 16: cvms.AttestationResponse
|
||||
(*AzureAttestationResponse)(nil), // 17: cvms.azureAttestationResponse
|
||||
(*timestamppb.Timestamp)(nil), // 18: google.protobuf.Timestamp
|
||||
}
|
||||
var file_agent_cvms_cvms_proto_depIdxs = []int32{
|
||||
17, // 0: cvms.AgentEvent.timestamp:type_name -> google.protobuf.Timestamp
|
||||
17, // 1: cvms.AgentLog.timestamp:type_name -> google.protobuf.Timestamp
|
||||
18, // 0: cvms.AgentEvent.timestamp:type_name -> google.protobuf.Timestamp
|
||||
18, // 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
|
||||
16, // 7: cvms.ClientStreamMessage.vTPMattestationReport:type_name -> cvms.AttestationResponse
|
||||
10, // 8: cvms.ServerStreamMessage.runReqChunks:type_name -> cvms.RunReqChunks
|
||||
11, // 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
|
||||
9, // 12: cvms.ServerStreamMessage.disconnectReq:type_name -> cvms.DisconnectReq
|
||||
13, // 13: cvms.ComputationRunReq.datasets:type_name -> cvms.Dataset
|
||||
14, // 14: cvms.ComputationRunReq.algorithm:type_name -> cvms.Algorithm
|
||||
12, // 15: cvms.ComputationRunReq.result_consumers:type_name -> cvms.ResultConsumer
|
||||
15, // 16: cvms.ComputationRunReq.agent_config:type_name -> cvms.AgentConfig
|
||||
7, // 17: cvms.Service.Process:input_type -> cvms.ClientStreamMessage
|
||||
8, // 18: cvms.Service.Process:output_type -> cvms.ServerStreamMessage
|
||||
18, // [18:19] is the sub-list for method output_type
|
||||
17, // [17:18] is the sub-list for method input_type
|
||||
17, // [17:17] is the sub-list for extension type_name
|
||||
17, // [17:17] is the sub-list for extension extendee
|
||||
0, // [0:17] is the sub-list for field type_name
|
||||
17, // 8: cvms.ClientStreamMessage.azureAttestationResult:type_name -> cvms.azureAttestationResponse
|
||||
10, // 9: cvms.ServerStreamMessage.runReqChunks:type_name -> cvms.RunReqChunks
|
||||
11, // 10: cvms.ServerStreamMessage.runReq:type_name -> cvms.ComputationRunReq
|
||||
2, // 11: cvms.ServerStreamMessage.stopComputation:type_name -> cvms.StopComputation
|
||||
0, // 12: cvms.ServerStreamMessage.agentStateReq:type_name -> cvms.AgentStateReq
|
||||
9, // 13: cvms.ServerStreamMessage.disconnectReq:type_name -> cvms.DisconnectReq
|
||||
13, // 14: cvms.ComputationRunReq.datasets:type_name -> cvms.Dataset
|
||||
14, // 15: cvms.ComputationRunReq.algorithm:type_name -> cvms.Algorithm
|
||||
12, // 16: cvms.ComputationRunReq.result_consumers:type_name -> cvms.ResultConsumer
|
||||
15, // 17: cvms.ComputationRunReq.agent_config:type_name -> cvms.AgentConfig
|
||||
7, // 18: cvms.Service.Process:input_type -> cvms.ClientStreamMessage
|
||||
8, // 19: cvms.Service.Process:output_type -> cvms.ServerStreamMessage
|
||||
19, // [19:20] is the sub-list for method output_type
|
||||
18, // [18:19] is the sub-list for method input_type
|
||||
18, // [18:18] is the sub-list for extension type_name
|
||||
18, // [18:18] is the sub-list for extension extendee
|
||||
0, // [0:18] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_agent_cvms_cvms_proto_init() }
|
||||
@@ -1428,6 +1509,7 @@ func file_agent_cvms_cvms_proto_init() {
|
||||
(*ClientStreamMessage_StopComputationRes)(nil),
|
||||
(*ClientStreamMessage_AgentStateRes)(nil),
|
||||
(*ClientStreamMessage_VTPMattestationReport)(nil),
|
||||
(*ClientStreamMessage_AzureAttestationResult)(nil),
|
||||
}
|
||||
file_agent_cvms_cvms_proto_msgTypes[8].OneofWrappers = []any{
|
||||
(*ServerStreamMessage_RunReqChunks)(nil),
|
||||
@@ -1442,7 +1524,7 @@ func file_agent_cvms_cvms_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: unsafe.Slice(unsafe.StringData(file_agent_cvms_cvms_proto_rawDesc), len(file_agent_cvms_cvms_proto_rawDesc)),
|
||||
NumEnums: 0,
|
||||
NumMessages: 17,
|
||||
NumMessages: 18,
|
||||
NumExtensions: 0,
|
||||
NumServices: 1,
|
||||
},
|
||||
|
||||
@@ -60,6 +60,7 @@ message ClientStreamMessage {
|
||||
StopComputationResponse stopComputationRes = 4;
|
||||
AgentStateRes agentStateRes = 5;
|
||||
AttestationResponse vTPMattestationReport = 6;
|
||||
azureAttestationResponse azureAttestationResult = 7;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,3 +123,8 @@ message AttestationResponse {
|
||||
bytes file = 1;
|
||||
string certSerialNumber = 2;
|
||||
}
|
||||
|
||||
message azureAttestationResponse {
|
||||
bytes file = 1;
|
||||
string certSerialNumber = 2;
|
||||
}
|
||||
|
||||
@@ -135,6 +135,66 @@ func (_c *Service_Attestation_Call) RunAndReturn(run func(context.Context, [64]b
|
||||
return _c
|
||||
}
|
||||
|
||||
// AttestationResult provides a mock function with given fields: ctx, nonce, attType
|
||||
func (_m *Service) AttestationResult(ctx context.Context, nonce [32]byte, attType attestation.PlatformType) ([]byte, error) {
|
||||
ret := _m.Called(ctx, nonce, attType)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for AttestationResult")
|
||||
}
|
||||
|
||||
var r0 []byte
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, [32]byte, attestation.PlatformType) ([]byte, error)); ok {
|
||||
return rf(ctx, nonce, attType)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, [32]byte, attestation.PlatformType) []byte); ok {
|
||||
r0 = rf(ctx, nonce, attType)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]byte)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, [32]byte, attestation.PlatformType) error); ok {
|
||||
r1 = rf(ctx, nonce, attType)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// Service_AttestationResult_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AttestationResult'
|
||||
type Service_AttestationResult_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// AttestationResult is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - nonce [32]byte
|
||||
// - attType attestation.PlatformType
|
||||
func (_e *Service_Expecter) AttestationResult(ctx interface{}, nonce interface{}, attType interface{}) *Service_AttestationResult_Call {
|
||||
return &Service_AttestationResult_Call{Call: _e.mock.On("AttestationResult", ctx, nonce, attType)}
|
||||
}
|
||||
|
||||
func (_c *Service_AttestationResult_Call) Run(run func(ctx context.Context, nonce [32]byte, attType attestation.PlatformType)) *Service_AttestationResult_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].([32]byte), args[2].(attestation.PlatformType))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Service_AttestationResult_Call) Return(_a0 []byte, _a1 error) *Service_AttestationResult_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Service_AttestationResult_Call) RunAndReturn(run func(context.Context, [32]byte, attestation.PlatformType) ([]byte, error)) *Service_AttestationResult_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Data provides a mock function with given fields: ctx, dataset
|
||||
func (_m *Service) Data(ctx context.Context, dataset agent.Dataset) error {
|
||||
ret := _m.Called(ctx, dataset)
|
||||
|
||||
@@ -106,6 +106,8 @@ var (
|
||||
ErrAttestationFailed = errors.New("failed to get raw quote")
|
||||
// ErrAttestationVTpmFailed vTPM attestation failed.
|
||||
ErrAttestationVTpmFailed = errors.New("failed to get vTPM quote")
|
||||
// ErrFetchAzureToken azure token fetch failed.
|
||||
ErrFetchAzureToken = errors.New("failed to get azure token")
|
||||
// ErrAttType indicates that the attestation type that is requested does not exist or is not supported.
|
||||
ErrAttestationType = errors.New("attestation type does not exist or is not supported")
|
||||
)
|
||||
@@ -120,6 +122,7 @@ type Service interface {
|
||||
Result(ctx context.Context) ([]byte, error)
|
||||
Attestation(ctx context.Context, reportData [quoteprovider.Nonce]byte, nonce [vtpm.Nonce]byte, attType attestation.PlatformType) ([]byte, error)
|
||||
IMAMeasurements(ctx context.Context) ([]byte, []byte, error)
|
||||
AttestationResult(ctx context.Context, nonce [vtpm.Nonce]byte, attType attestation.PlatformType) ([]byte, error)
|
||||
State() string
|
||||
}
|
||||
|
||||
@@ -447,6 +450,19 @@ func (as *agentService) Attestation(ctx context.Context, reportData [quoteprovid
|
||||
}
|
||||
}
|
||||
|
||||
func (as *agentService) AttestationResult(ctx context.Context, nonce [vtpm.Nonce]byte, attType attestation.PlatformType) ([]byte, error) {
|
||||
switch attType {
|
||||
case attestation.AzureToken:
|
||||
token, err := as.provider.AzureAttestationToken(nonce[:])
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
return token, nil
|
||||
default:
|
||||
return []byte{}, ErrAttestationType
|
||||
}
|
||||
}
|
||||
|
||||
func (as *agentService) runComputation(state statemachine.State) {
|
||||
as.publishEvent(Starting.String())(state)
|
||||
as.logger.Debug("computation run started")
|
||||
|
||||
@@ -400,6 +400,58 @@ func TestAttestation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAttestationResult(t *testing.T) {
|
||||
provider := new(mocks2.Provider)
|
||||
cases := []struct {
|
||||
name string
|
||||
nonce [vtpm.Nonce]byte
|
||||
platform attestation.PlatformType
|
||||
token []byte
|
||||
err error
|
||||
}{
|
||||
{
|
||||
name: "Azure token fetch successful",
|
||||
nonce: [32]byte{1, 2, 3}, // any test nonce
|
||||
platform: attestation.AzureToken,
|
||||
token: []byte("mockToken"),
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
name: "Azure token fetch failed",
|
||||
nonce: [32]byte{4, 5, 6},
|
||||
platform: attestation.AzureToken,
|
||||
token: []byte{},
|
||||
err: ErrFetchAzureToken,
|
||||
},
|
||||
{
|
||||
name: "Invalid attestation type",
|
||||
nonce: [32]byte{7, 8, 9},
|
||||
platform: attestation.SNP,
|
||||
token: []byte{},
|
||||
err: ErrAttestationType,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
events := new(mocks.Service)
|
||||
events.EXPECT().SendEvent(mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return()
|
||||
|
||||
if tc.platform == attestation.AzureToken {
|
||||
provider.On("AzureAttestationToken", tc.nonce[:]).Return(tc.token, tc.err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
svc := New(ctx, mglog.NewMock(), events, provider, 0)
|
||||
|
||||
result, err := svc.AttestationResult(ctx, tc.nonce, tc.platform)
|
||||
assert.True(t, errors.Contains(err, tc.err), "expected error %v, got %v", tc.err, err)
|
||||
assert.Equal(t, tc.token, result)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func generateReportData() [quoteprovider.Nonce]byte {
|
||||
bytes := make([]byte, quoteprovider.Nonce)
|
||||
_, err := rand.Read(bytes)
|
||||
|
||||
+167
-76
@@ -3,6 +3,7 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
@@ -32,29 +33,31 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
defaultMinimumTcb = 0
|
||||
defaultMinimumLaunchTcb = 0
|
||||
defaultMinimumGuestSvn = 0
|
||||
defaultGuestPolicy = 0x0000000000030000
|
||||
defaultMinimumBuild = 0
|
||||
defaultCheckCrl = false
|
||||
defaultTimeout = 2 * time.Minute
|
||||
defaultMaxRetryDelay = 30 * time.Second
|
||||
defaultRequireAuthor = false
|
||||
defaultRequireIdBlock = false
|
||||
defaultMinVersion = "0.0"
|
||||
size16 = 16
|
||||
size32 = 32
|
||||
size48 = 48
|
||||
size64 = 64
|
||||
attestationFilePath = "attestation.bin"
|
||||
vtpmFilePath = "../quote.dat"
|
||||
attestationJson = "attestation.json"
|
||||
sevProductNameMilan = "Milan"
|
||||
sevProductNameGenoa = "Genoa"
|
||||
FormatBinaryPB = "binarypb"
|
||||
FormatTextProto = "textproto"
|
||||
exampleJSONConfig = `
|
||||
defaultMinimumTcb = 0
|
||||
defaultMinimumLaunchTcb = 0
|
||||
defaultMinimumGuestSvn = 0
|
||||
defaultGuestPolicy = 0x0000000000030000
|
||||
defaultMinimumBuild = 0
|
||||
defaultCheckCrl = false
|
||||
defaultTimeout = 2 * time.Minute
|
||||
defaultMaxRetryDelay = 30 * time.Second
|
||||
defaultRequireAuthor = false
|
||||
defaultRequireIdBlock = false
|
||||
defaultMinVersion = "0.0"
|
||||
size16 = 16
|
||||
size32 = 32
|
||||
size48 = 48
|
||||
size64 = 64
|
||||
attestationFilePath = "attestation.bin"
|
||||
azureAttestResultFilePath = "azure_attest_result.json"
|
||||
azureAttestTokenFilePath = "azure_attest_token.jwt"
|
||||
vtpmFilePath = "../quote.dat"
|
||||
attestationReportJson = "attestation.json"
|
||||
sevProductNameMilan = "Milan"
|
||||
sevProductNameGenoa = "Genoa"
|
||||
FormatBinaryPB = "binarypb"
|
||||
FormatTextProto = "textproto"
|
||||
exampleJSONConfig = `
|
||||
{
|
||||
"rootOfTrust":{
|
||||
"product":"test_product",
|
||||
@@ -107,41 +110,44 @@ const (
|
||||
}
|
||||
}
|
||||
`
|
||||
SNP = "snp"
|
||||
VTPM = "vtpm"
|
||||
SNPvTPM = "snp-vtpm"
|
||||
CCNone = "none"
|
||||
CCAzure = "azure"
|
||||
CCGCP = "gcp"
|
||||
SNP = "snp"
|
||||
VTPM = "vtpm"
|
||||
SNPvTPM = "snp-vtpm"
|
||||
AzureToken = "azure-token"
|
||||
CCNone = "none"
|
||||
CCAzure = "azure"
|
||||
CCGCP = "gcp"
|
||||
)
|
||||
|
||||
var (
|
||||
mode string
|
||||
cfg = check.Config{Policy: &check.Policy{}, RootOfTrust: &check.RootOfTrust{}}
|
||||
cfgString string
|
||||
timeout time.Duration
|
||||
maxRetryDelay time.Duration
|
||||
platformInfo string
|
||||
stepping string
|
||||
trustedAuthorKeys []string
|
||||
trustedAuthorHashes []string
|
||||
trustedIdKeys []string
|
||||
trustedIdKeyHashes []string
|
||||
attestationFile string
|
||||
tpmAttestationFile string
|
||||
attestationRaw []byte
|
||||
empty16 = [size16]byte{}
|
||||
empty32 = [size32]byte{}
|
||||
empty64 = [size64]byte{}
|
||||
defaultReportIdMa = []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}
|
||||
errReportSize = errors.New("attestation contents too small")
|
||||
ErrBadAttestation = errors.New("attestation file is corrupted or in wrong format")
|
||||
output string
|
||||
nonce []byte
|
||||
format string
|
||||
teeNonce []byte
|
||||
getTextProtoAttestation bool
|
||||
cloud string
|
||||
mode string
|
||||
cfg = check.Config{Policy: &check.Policy{}, RootOfTrust: &check.RootOfTrust{}}
|
||||
cfgString string
|
||||
timeout time.Duration
|
||||
maxRetryDelay time.Duration
|
||||
platformInfo string
|
||||
stepping string
|
||||
trustedAuthorKeys []string
|
||||
trustedAuthorHashes []string
|
||||
trustedIdKeys []string
|
||||
trustedIdKeyHashes []string
|
||||
attestationFile string
|
||||
tpmAttestationFile string
|
||||
attestationRaw []byte
|
||||
empty16 = [size16]byte{}
|
||||
empty32 = [size32]byte{}
|
||||
empty64 = [size64]byte{}
|
||||
defaultReportIdMa = []byte{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}
|
||||
errReportSize = errors.New("attestation contents too small")
|
||||
ErrBadAttestation = errors.New("attestation file is corrupted or in wrong format")
|
||||
output string
|
||||
nonce []byte
|
||||
format string
|
||||
teeNonce []byte
|
||||
tokenNonce []byte
|
||||
getTextProtoAttestationReport bool
|
||||
getAzureTokenJWT bool
|
||||
cloud string
|
||||
)
|
||||
|
||||
var errEmptyFile = errors.New("input file is empty")
|
||||
@@ -180,11 +186,12 @@ func (cli *CLI) NewGetAttestationCmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "get",
|
||||
Short: "Retrieve attestation information from agent. The argument of the command must be the type of the report (snp or vtpm or snp-vtpm).",
|
||||
ValidArgs: []cobra.Completion{SNP, VTPM, SNPvTPM},
|
||||
ValidArgs: []cobra.Completion{SNP, VTPM, SNPvTPM, AzureToken},
|
||||
Example: fmt.Sprintf(`Based on attestation report type:
|
||||
get %s --tee <512 bit hex value>
|
||||
get %s --vtpm <256 bit hex value>
|
||||
get %s --tee <512 bit hex value> --vtpm <256 bit hex value>`, SNP, VTPM, SNPvTPM),
|
||||
get %s --tee <512 bit hex value> --vtpm <256 bit hex value>
|
||||
get %s --token <256 bit hex value>`, SNP, VTPM, SNPvTPM, AzureToken),
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if cli.connectErr != nil {
|
||||
@@ -209,6 +216,9 @@ func (cli *CLI) NewGetAttestationCmd() *cobra.Command {
|
||||
case SNPvTPM:
|
||||
cmd.Println("Fetching SEV-SNP and vTPM report")
|
||||
attType = attestation.SNPvTPM
|
||||
case AzureToken:
|
||||
cmd.Println("Fetching Azure token")
|
||||
attType = attestation.AzureToken
|
||||
}
|
||||
|
||||
if (attType == attestation.VTPM || attType == attestation.SNPvTPM) && len(nonce) == 0 {
|
||||
@@ -223,8 +233,14 @@ func (cli *CLI) NewGetAttestationCmd() *cobra.Command {
|
||||
return
|
||||
}
|
||||
|
||||
if (attType == attestation.AzureToken) && len(tokenNonce) == 0 {
|
||||
msg := color.New(color.FgRed).Sprint("Token nonce must be defined for Azure attestation ❌ ")
|
||||
cmd.Println(msg)
|
||||
return
|
||||
}
|
||||
|
||||
var fixedReportData [quoteprovider.Nonce]byte
|
||||
if attType != attestation.VTPM {
|
||||
if attType == attestation.SNP || attType == attestation.SNPvTPM {
|
||||
if len(teeNonce) > quoteprovider.Nonce {
|
||||
msg := color.New(color.FgRed).Sprintf("nonce must be a hex encoded string of length lesser or equal %d bytes ❌ ", quoteprovider.Nonce)
|
||||
cmd.Println(msg)
|
||||
@@ -236,18 +252,28 @@ func (cli *CLI) NewGetAttestationCmd() *cobra.Command {
|
||||
|
||||
var fixedVtpmNonceByte [vtpm.Nonce]byte
|
||||
if attType != attestation.SNP {
|
||||
if len(nonce) > vtpm.Nonce {
|
||||
if (len(nonce) > vtpm.Nonce) || (len(tokenNonce) > vtpm.Nonce) {
|
||||
msg := color.New(color.FgRed).Sprintf("vTPM nonce must be a hex encoded string of length lesser or equal %d bytes ❌ ", vtpm.Nonce)
|
||||
cmd.Println(msg)
|
||||
return
|
||||
}
|
||||
|
||||
copy(fixedVtpmNonceByte[:], nonce)
|
||||
if attType == attestation.AzureToken {
|
||||
copy(fixedVtpmNonceByte[:], tokenNonce)
|
||||
} else {
|
||||
copy(fixedVtpmNonceByte[:], nonce)
|
||||
}
|
||||
}
|
||||
|
||||
filename := attestationFilePath
|
||||
if getTextProtoAttestation {
|
||||
filename = attestationJson
|
||||
|
||||
if attType == attestation.AzureToken {
|
||||
filename = azureAttestResultFilePath
|
||||
}
|
||||
|
||||
if getTextProtoAttestationReport {
|
||||
filename = attestationReportJson
|
||||
} else if getAzureTokenJWT {
|
||||
filename = azureAttestTokenFilePath
|
||||
}
|
||||
|
||||
attestationFile, err := os.Create(filename)
|
||||
@@ -256,9 +282,21 @@ func (cli *CLI) NewGetAttestationCmd() *cobra.Command {
|
||||
return
|
||||
}
|
||||
|
||||
if err := cli.agentSDK.Attestation(cmd.Context(), fixedReportData, fixedVtpmNonceByte, int(attType), attestationFile); err != nil {
|
||||
printError(cmd, "Failed to get attestation due to error: %v ❌ ", err)
|
||||
return
|
||||
var returnJsonAzureToken bool
|
||||
|
||||
if attType == attestation.AzureToken {
|
||||
err := cli.agentSDK.AttestationResult(cmd.Context(), fixedVtpmNonceByte, int(attType), attestationFile)
|
||||
if err != nil {
|
||||
printError(cmd, "Failed to get attestation result due to error: %v ❌", err)
|
||||
return
|
||||
}
|
||||
returnJsonAzureToken = !getAzureTokenJWT
|
||||
} else {
|
||||
err := cli.agentSDK.Attestation(cmd.Context(), fixedReportData, fixedVtpmNonceByte, int(attType), attestationFile)
|
||||
if err != nil {
|
||||
printError(cmd, "Failed to get attestation due to error: %v ❌", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := attestationFile.Close(); err != nil {
|
||||
@@ -266,7 +304,7 @@ func (cli *CLI) NewGetAttestationCmd() *cobra.Command {
|
||||
return
|
||||
}
|
||||
|
||||
if getTextProtoAttestation {
|
||||
if getTextProtoAttestationReport || returnJsonAzureToken {
|
||||
result, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
printError(cmd, "Error reading attestation file: %v ❌ ", err)
|
||||
@@ -276,6 +314,11 @@ func (cli *CLI) NewGetAttestationCmd() *cobra.Command {
|
||||
switch attestationType {
|
||||
case SNP:
|
||||
result, err = attesationToJSON(result)
|
||||
if err != nil {
|
||||
printError(cmd, "Error converting SNP attestation to JSON: %v ❌", err)
|
||||
return
|
||||
}
|
||||
|
||||
case VTPM, SNPvTPM:
|
||||
marshalOptions := prototext.MarshalOptions{
|
||||
Multiline: true,
|
||||
@@ -284,15 +327,17 @@ func (cli *CLI) NewGetAttestationCmd() *cobra.Command {
|
||||
var attvTPM tpmAttest.Attestation
|
||||
err = proto.Unmarshal(result, &attvTPM)
|
||||
if err != nil {
|
||||
printError(cmd, "failed to unmarshal the attestation report: %v ❌ ", ErrBadAttestation)
|
||||
printError(cmd, "Failed to unmarshal the attestation report: %v ❌", err)
|
||||
return
|
||||
}
|
||||
|
||||
result = []byte(marshalOptions.Format(&attvTPM))
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
printError(cmd, "Error converting attestation to textproto: %v ❌ ", err)
|
||||
return
|
||||
case AzureToken:
|
||||
result, err = decodeJWTToJSON(result)
|
||||
if err != nil {
|
||||
printError(cmd, "Error decoding Azure token: %v ❌", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err := os.WriteFile(filename, result, 0o644); err != nil {
|
||||
@@ -305,9 +350,11 @@ func (cli *CLI) NewGetAttestationCmd() *cobra.Command {
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVarP(&getTextProtoAttestation, "textproto", "p", false, "Get attestation in textproto format")
|
||||
cmd.Flags().BytesHexVarP(&teeNonce, "tee", "e", []byte{}, "Define the nonce for the SNP attestation report (must be used with attestation type snp and snp-vtpm)")
|
||||
cmd.Flags().BytesHexVarP(&nonce, "vtpm", "t", []byte{}, "Define the nonce for the vTPM attestation report (must be used with attestation type vtpm and snp-vtpm)")
|
||||
cmd.Flags().BoolVarP(&getAzureTokenJWT, "azurejwt", "t", false, "Get azure attestation token as jwt format")
|
||||
cmd.Flags().BoolVarP(&getTextProtoAttestationReport, "reporttextproto", "r", false, "Get attestation report in textproto format")
|
||||
cmd.Flags().BytesHexVar(&teeNonce, "tee", []byte{}, "Define the nonce for the SNP attestation report (must be used with attestation type snp and snp-vtpm)")
|
||||
cmd.Flags().BytesHexVar(&nonce, "vtpm", []byte{}, "Define the nonce for the vTPM attestation report (must be used with attestation type vtpm and snp-vtpm)")
|
||||
cmd.Flags().BytesHexVar(&tokenNonce, "token", []byte{}, "Define the nonce for the Azure attestation token (must be used with attestation type azure-token)")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -1036,3 +1083,47 @@ func validateFieldLength(fieldName string, field []byte, expectedLength int) err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func decodeJWTToJSON(tokenBytes []byte) ([]byte, error) {
|
||||
token := string(tokenBytes) // convert to string
|
||||
parts := strings.Split(token, ".")
|
||||
if len(parts) < 2 {
|
||||
return nil, fmt.Errorf("invalid JWT: must have at least 2 parts")
|
||||
}
|
||||
|
||||
decode := func(seg string) (map[string]interface{}, error) {
|
||||
// Add padding if missing
|
||||
if m := len(seg) % 4; m != 0 {
|
||||
seg += strings.Repeat("=", 4-m)
|
||||
}
|
||||
|
||||
data, err := base64.URLEncoding.DecodeString(seg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var result map[string]interface{}
|
||||
if err := json.Unmarshal(data, &result); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
header, err := decode(parts[0])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode header: %v", err)
|
||||
}
|
||||
|
||||
payload, err := decode(parts[1])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode payload: %v", err)
|
||||
}
|
||||
|
||||
combined := map[string]interface{}{
|
||||
"header": header,
|
||||
"payload": payload,
|
||||
}
|
||||
|
||||
return json.MarshalIndent(combined, "", " ")
|
||||
}
|
||||
|
||||
+87
-7
@@ -49,6 +49,7 @@ func TestNewGetAttestationCmd(t *testing.T) {
|
||||
|
||||
teeNonce := hex.EncodeToString(bytes.Repeat([]byte{0x00}, quoteprovider.Nonce))
|
||||
vtpmNonce := hex.EncodeToString(bytes.Repeat([]byte{0x00}, vtpm.Nonce))
|
||||
tokenNonce := hex.EncodeToString(bytes.Repeat([]byte{0x00}, vtpm.Nonce))
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
@@ -102,7 +103,7 @@ func TestNewGetAttestationCmd(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "invalid vTPM data size",
|
||||
args: []string{"vtpm", "-t", hex.EncodeToString(bytes.Repeat([]byte{0x00}, 33))},
|
||||
args: []string{"vtpm", "--vtpm", hex.EncodeToString(bytes.Repeat([]byte{0x00}, 33))},
|
||||
mockResponse: nil,
|
||||
mockError: errors.New("error"),
|
||||
expectedErr: "vTPM nonce must be a hex encoded string of length lesser or equal 32 bytes",
|
||||
@@ -116,39 +117,60 @@ func TestNewGetAttestationCmd(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "failed to get attestation",
|
||||
args: []string{"snp", "-e", teeNonce},
|
||||
args: []string{"snp", "--tee", teeNonce},
|
||||
mockResponse: nil,
|
||||
mockError: errors.New("error"),
|
||||
expectedErr: "Failed to get attestation due to error",
|
||||
},
|
||||
{
|
||||
name: "Textproto report error",
|
||||
args: []string{"snp", "-e", teeNonce, "--textproto"},
|
||||
args: []string{"snp", "--tee", teeNonce, "--reporttextproto"},
|
||||
mockResponse: []byte("mock attestation"),
|
||||
mockError: nil,
|
||||
expectedErr: "Error converting attestation to textproto",
|
||||
expectedErr: "Fetching SEV-SNP attestation report\nError converting SNP attestation to JSON: attestation contents too small : attestation contents too small (0x10 bytes). Want at least 0x4a0 bytes ❌\n",
|
||||
},
|
||||
{
|
||||
name: "successful Textproto report",
|
||||
args: []string{"snp", "-e", teeNonce, "--textproto"},
|
||||
args: []string{"snp", "--tee", teeNonce, "--reporttextproto"},
|
||||
mockResponse: validattestation,
|
||||
mockError: nil,
|
||||
expectedOut: "Attestation result retrieved and saved successfully!",
|
||||
},
|
||||
{
|
||||
name: "connection error",
|
||||
args: []string{"snp", "-e", teeNonce},
|
||||
args: []string{"snp", "--tee", teeNonce},
|
||||
mockResponse: nil,
|
||||
mockError: errors.New("failed to connect to agent"),
|
||||
expectedErr: "Failed to connect to agent",
|
||||
},
|
||||
{
|
||||
name: "successful Azure token retrieval",
|
||||
args: []string{"azure-token", "--token", tokenNonce},
|
||||
mockResponse: []byte("eyJhbGciOiAiUlMyNTYifQ.eyJzdWIiOiAidGVzdC11c2VyIn0.signature"),
|
||||
mockError: nil,
|
||||
expectedOut: "Fetching Azure token\nAttestation result retrieved and saved successfully!\n",
|
||||
},
|
||||
{
|
||||
name: "failed to retrieve Azure token",
|
||||
args: []string{"azure-token", "--token", tokenNonce},
|
||||
mockResponse: nil,
|
||||
mockError: errors.New("error"),
|
||||
expectedErr: "Fetching Azure token\nFailed to get attestation result due to error: error ❌\n",
|
||||
},
|
||||
{
|
||||
name: "invalid token nonce size",
|
||||
args: []string{"azure-token", "--token", hex.EncodeToString(bytes.Repeat([]byte{0x00}, 33))},
|
||||
mockResponse: nil,
|
||||
mockError: errors.New("error"),
|
||||
expectedErr: "Fetching Azure token\nvTPM nonce must be a hex encoded string of length lesser or equal 32 bytes ❌ \n",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Cleanup(func() {
|
||||
os.Remove(attestationFilePath)
|
||||
os.Remove(attestationJson)
|
||||
os.Remove(attestationReportJson)
|
||||
})
|
||||
mockSDK := new(mocks.SDK)
|
||||
cli := &CLI{agentSDK: mockSDK}
|
||||
@@ -164,6 +186,11 @@ func TestNewGetAttestationCmd(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
mockSDK.On("AttestationResult", mock.Anything, [vtpm.Nonce]byte(bytes.Repeat([]byte{0x00}, vtpm.Nonce)), mock.Anything, mock.Anything).Return(tc.mockError).Run(func(args mock.Arguments) {
|
||||
_, err := args.Get(3).(*os.File).Write(tc.mockResponse)
|
||||
require.NoError(t, err)
|
||||
})
|
||||
|
||||
cmd.SetArgs(tc.args)
|
||||
err := cmd.Execute()
|
||||
|
||||
@@ -627,3 +654,56 @@ func TestRoundTrip(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, roundTripReport)
|
||||
}
|
||||
|
||||
func TestDecodeJWTToJSON(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input []byte
|
||||
err error
|
||||
validate func(t *testing.T, output []byte)
|
||||
}{
|
||||
{
|
||||
name: "Valid JWT",
|
||||
input: []byte("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." +
|
||||
"eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ." +
|
||||
"SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c"),
|
||||
err: nil,
|
||||
validate: func(t *testing.T, output []byte) {
|
||||
assert.NotEmpty(t, output)
|
||||
assert.Contains(t, string(output), `"header"`)
|
||||
assert.Contains(t, string(output), `"payload"`)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Invalid JWT - one part",
|
||||
input: []byte("justonepart"),
|
||||
err: fmt.Errorf("invalid JWT: must have at least 2 parts"),
|
||||
validate: func(t *testing.T, output []byte) {
|
||||
assert.Nil(t, output)
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "Invalid Base64",
|
||||
input: []byte("bad@@@.header"),
|
||||
err: errors.New("illegal base64 data"),
|
||||
validate: func(t *testing.T, output []byte) {
|
||||
assert.Nil(t, output)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := decodeJWTToJSON(tt.input)
|
||||
|
||||
if tt.err != nil {
|
||||
assert.Error(t, err)
|
||||
assert.Contains(t, err.Error(), tt.err.Error())
|
||||
} else {
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
tt.validate(t, got)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
+49
-5
@@ -19,7 +19,6 @@ import (
|
||||
mglog "github.com/absmach/magistrala/logger"
|
||||
"github.com/absmach/magistrala/pkg/prometheus"
|
||||
"github.com/caarlos0/env/v11"
|
||||
"github.com/edgelesssys/go-azguestattestation/maa"
|
||||
"github.com/ultravioletrs/cocos/agent"
|
||||
"github.com/ultravioletrs/cocos/agent/api"
|
||||
"github.com/ultravioletrs/cocos/agent/cvms"
|
||||
@@ -89,6 +88,14 @@ func main() {
|
||||
var provider attestation.Provider
|
||||
ccPlatform := attestation.CCPlatform()
|
||||
|
||||
azureConfig := azure.NewEnvConfigFromAgent(
|
||||
cfg.AgentOSBuild,
|
||||
cfg.AgentOSType,
|
||||
cfg.AgentOSDistro,
|
||||
cfg.AgentMaaURL,
|
||||
)
|
||||
azure.InitializeDefaultMAAVars(azureConfig)
|
||||
|
||||
switch ccPlatform {
|
||||
case attestation.SNP:
|
||||
provider = vtpm.New(nil, false, uint(cfg.Vmpl), nil)
|
||||
@@ -144,10 +151,6 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
azure.MaaURL = cfg.AgentMaaURL
|
||||
maa.OSBuild = cfg.AgentOSBuild
|
||||
maa.OSDistro = cfg.AgentOSDistro
|
||||
maa.OSType = cfg.AgentOSType
|
||||
svc := newService(ctx, logger, eventSvc, provider, cfg.Vmpl)
|
||||
|
||||
if err := os.MkdirAll(storageDir, 0o755); err != nil {
|
||||
@@ -189,6 +192,13 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
azureAttestationResult, azureCertSerialNumber, err := azureAttestationFromCert(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{
|
||||
@@ -198,6 +208,15 @@ func main() {
|
||||
},
|
||||
}
|
||||
|
||||
eventsLogsQueue <- &cvms.ClientStreamMessage{
|
||||
Message: &cvms.ClientStreamMessage_AzureAttestationResult{
|
||||
AzureAttestationResult: &cvms.AzureAttestationResponse{
|
||||
File: azureAttestationResult,
|
||||
CertSerialNumber: azureCertSerialNumber,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if err := g.Wait(); err != nil {
|
||||
logger.Error(fmt.Sprintf("%s service terminated: %s", svcName, err))
|
||||
}
|
||||
@@ -238,3 +257,28 @@ func attestationFromCert(ctx context.Context, certFilePath string, svc agent.Ser
|
||||
|
||||
return attest, certx509.SerialNumber.String(), nil
|
||||
}
|
||||
|
||||
func azureAttestationFromCert(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
|
||||
}
|
||||
|
||||
nonceAzure := sha256.Sum256(certFile)
|
||||
attestation, err := svc.AttestationResult(ctx, nonceAzure, attestation.AzureToken)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
|
||||
return attestation, certx509.SerialNumber.String(), nil
|
||||
}
|
||||
|
||||
@@ -26,8 +26,9 @@ require (
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go/compute/metadata v0.6.0
|
||||
cloud.google.com/go/storage v1.51.0
|
||||
github.com/edgelesssys/go-azguestattestation v0.0.0-20250408071817-8c4457b235ff
|
||||
github.com/golang-jwt/jwt/v4 v4.5.1
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||
github.com/google/gce-tcb-verifier v0.3.1
|
||||
)
|
||||
@@ -37,7 +38,7 @@ require (
|
||||
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/confidentialcomputing v1.8.0 // indirect
|
||||
cloud.google.com/go/iam v1.4.1 // indirect
|
||||
cloud.google.com/go/monitoring v1.24.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect
|
||||
@@ -46,7 +47,9 @@ require (
|
||||
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/errdefs v0.3.0 // indirect
|
||||
github.com/containerd/log v0.1.0 // indirect
|
||||
github.com/containerd/ttrpc v1.2.7 // 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
|
||||
@@ -56,6 +59,7 @@ require (
|
||||
github.com/go-jose/go-jose/v3 v3.0.3 // indirect
|
||||
github.com/gofrs/uuid/v5 v5.3.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/google/certificate-transparency-go v1.1.8 // indirect
|
||||
github.com/google/go-attestation v0.5.1 // indirect
|
||||
github.com/google/go-eventlog v0.0.2-0.20241003021507-01bb555f7cba // indirect
|
||||
@@ -73,6 +77,7 @@ require (
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/pelletier/go-toml v1.9.5 // indirect
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.34.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
|
||||
@@ -95,16 +100,18 @@ require (
|
||||
github.com/absmach/certs v0.0.0-20250313105043-afbcda9a9963
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/containerd/containerd v1.7.27
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/docker/docker v28.0.1+incompatible
|
||||
github.com/docker/docker v28.0.4+incompatible
|
||||
github.com/edgelesssys/go-azguestattestation v0.0.0-20250408071817-8c4457b235ff
|
||||
github.com/go-kit/log v0.2.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.6.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||
github.com/google/go-configfs-tsm v0.3.3-0.20240919001351-b4b5b84fdcbc // indirect
|
||||
github.com/google/go-tpm v0.9.3
|
||||
github.com/google/go-tpm-tools v0.4.4
|
||||
github.com/google/go-tpm-tools/verifier v0.0.0-20250401045350-423d6a29a6d4
|
||||
github.com/google/logger v1.1.1
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.26.1 // indirect
|
||||
|
||||
@@ -8,6 +8,8 @@ cloud.google.com/go/auth/oauth2adapt v0.2.7 h1:/Lc7xODdqcEw8IrZ9SvwnlLX6j9FHQM74
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.7/go.mod h1:NTbTTzfvPl1Y3V1nPpOgl2w6d/FjO7NNUQaWSox6ZMc=
|
||||
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/confidentialcomputing v1.8.0 h1:Ww6t7uhIqC21N+nFTRzb+UJbXRp6bBhhY3bGxc5mK/Y=
|
||||
cloud.google.com/go/confidentialcomputing v1.8.0/go.mod h1:XxFLLdm6WINyCXqpFDJArVYThgtgD3yHmbhteIJADgQ=
|
||||
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/logging v1.13.0 h1:7j0HgAp0B94o1YRDqiqm26w4q1rDMH7XNRU34lJXHYc=
|
||||
@@ -48,18 +50,25 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
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/containerd/containerd v1.7.27 h1:yFyEyojddO3MIGVER2xJLWoCIn+Up4GaHFquP7hsFII=
|
||||
github.com/containerd/containerd v1.7.27/go.mod h1:xZmPnl75Vc+BLGt4MIfu6bp+fy03gdHAn9bz+FreFR0=
|
||||
github.com/containerd/errdefs v0.3.0 h1:FSZgGOeK4yuT/+DnF07/Olde/q4KBoMsaamhXxIMDp4=
|
||||
github.com/containerd/errdefs v0.3.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||
github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I=
|
||||
github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo=
|
||||
github.com/containerd/ttrpc v1.2.7 h1:qIrroQvuOL9HQ1X6KHe2ohc7p+HP/0VE6XPU7elJRqQ=
|
||||
github.com/containerd/ttrpc v1.2.7/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/danko-miladinovic/go-tpm-tools v0.0.0-20250228160324-1ebcfd79567c h1:gFo8kqRXFoM6ttqMrK+M3xffxco+Yj80kUo3NoMe8LU=
|
||||
github.com/danko-miladinovic/go-tpm-tools v0.0.0-20250228160324-1ebcfd79567c/go.mod h1:ktjTNq8yZFD6TzdBFefUfen96rF3NpYwpSb2d8bc+Y8=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk=
|
||||
github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
|
||||
github.com/docker/docker v28.0.1+incompatible h1:FCHjSRdXhNRFjlHMTv4jUNlIBbTeRjrWfeFuJp7jpo0=
|
||||
github.com/docker/docker v28.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v28.0.4+incompatible h1:JNNkBctYKurkw6FrHfKqY0nKIDf5nrbxjVBtS+cdcok=
|
||||
github.com/docker/docker v28.0.4+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
|
||||
github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
@@ -101,6 +110,8 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.1 h1:JdqV9zKUdtaa9gdPlywC3aeoEsR681PlKC+4F5gQgeo=
|
||||
github.com/golang-jwt/jwt/v4 v4.5.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
|
||||
@@ -125,6 +136,8 @@ github.com/google/go-tdx-guest v0.3.2-0.20241009005452-097ee70d0843 h1:+MoPobRN9
|
||||
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=
|
||||
github.com/google/go-tpm v0.9.3/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
||||
github.com/google/go-tpm-tools/verifier v0.0.0-20250401045350-423d6a29a6d4 h1:prG49QOVZnUgzHBEXEVpqRWwI1WpgPm75NG/iVPQM4g=
|
||||
github.com/google/go-tpm-tools/verifier v0.0.0-20250401045350-423d6a29a6d4/go.mod h1:hQ5bR5qES5FMITR7zt0ZqKrtpMhlLYBWwYjx2Uud3Lw=
|
||||
github.com/google/go-tspi v0.3.0 h1:ADtq8RKfP+jrTyIWIZDIYcKOMecRqNJFOew2IT0Inus=
|
||||
github.com/google/go-tspi v0.3.0/go.mod h1:xfMGI3G0PhxCdNVcYr1C4C+EizojDg/TXuX5by8CiHI=
|
||||
github.com/google/logger v1.1.1 h1:+6Z2geNxc9G+4D4oDO9njjjn2d0wN5d7uOo0vOIW1NQ=
|
||||
@@ -288,6 +301,7 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
|
||||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
||||
@@ -23,6 +23,7 @@ const (
|
||||
SNP PlatformType = iota
|
||||
VTPM
|
||||
SNPvTPM
|
||||
AzureToken
|
||||
Azure
|
||||
NoCC
|
||||
)
|
||||
@@ -67,6 +68,7 @@ type Provider interface {
|
||||
VerifyAttestation(report []byte, teeNonce []byte, vTpmNonce []byte) error
|
||||
VerifTeeAttestation(report []byte, teeNonce []byte) error
|
||||
VerifVTpmAttestation(report []byte, vTpmNonce []byte) error
|
||||
AzureAttestationToken(tokenNonce []byte) ([]byte, error)
|
||||
}
|
||||
|
||||
func ReadAttestationPolicy(policyPath string, attestationConfiguration *Config) error {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
// Copyright (c) Ultraviolet
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package azure
|
||||
|
||||
import (
|
||||
"github.com/edgelesssys/go-azguestattestation/maa"
|
||||
)
|
||||
|
||||
type EnvConfig struct {
|
||||
OSBuild string
|
||||
OSType string
|
||||
OSDistro string
|
||||
MaaURL string
|
||||
}
|
||||
|
||||
func NewEnvConfigFromAgent(agentOSBuild, agentOSType, agentOSDistro, maaURL string) *EnvConfig {
|
||||
return &EnvConfig{
|
||||
OSBuild: agentOSBuild,
|
||||
OSType: agentOSType,
|
||||
OSDistro: agentOSDistro,
|
||||
MaaURL: maaURL,
|
||||
}
|
||||
}
|
||||
|
||||
func InitializeDefaultMAAVars(config *EnvConfig) {
|
||||
maa.OSBuild = config.OSBuild
|
||||
maa.OSType = config.OSType
|
||||
maa.OSDistro = config.OSDistro
|
||||
}
|
||||
|
||||
func (c *EnvConfig) InitializeOSVars(build, osType, osDistro string) {
|
||||
if build != "" {
|
||||
c.OSBuild = build
|
||||
}
|
||||
if osType != "" {
|
||||
c.OSType = osType
|
||||
}
|
||||
if osDistro != "" {
|
||||
c.OSDistro = osDistro
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) Ultraviolet
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package azure
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/edgelesssys/go-azguestattestation/maa"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestNewEnvConfigFromAgent(t *testing.T) {
|
||||
// Given
|
||||
expectedBuild := "CustomBuild123"
|
||||
expectedType := "Linux"
|
||||
expectedDistro := "UVC-Debian"
|
||||
expectedURL := "https://test.attest.azure.net"
|
||||
|
||||
// When
|
||||
cfg := NewEnvConfigFromAgent(expectedBuild, expectedType, expectedDistro, expectedURL)
|
||||
|
||||
// Then
|
||||
if cfg.OSBuild != expectedBuild {
|
||||
t.Errorf("expected OSBuild = %s, got %s", expectedBuild, cfg.OSBuild)
|
||||
}
|
||||
if cfg.OSType != expectedType {
|
||||
t.Errorf("expected OSType = %s, got %s", expectedType, cfg.OSType)
|
||||
}
|
||||
if cfg.OSDistro != expectedDistro {
|
||||
t.Errorf("expected OSDistro = %s, got %s", expectedDistro, cfg.OSDistro)
|
||||
}
|
||||
if cfg.MaaURL != expectedURL {
|
||||
t.Errorf("expected MaaURL = %s, got %s", expectedURL, cfg.MaaURL)
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitializeDefaultMAAVars(t *testing.T) {
|
||||
cfg := &EnvConfig{
|
||||
OSBuild: "build123",
|
||||
OSType: "CustomOS",
|
||||
OSDistro: "DistroX",
|
||||
}
|
||||
InitializeDefaultMAAVars(cfg)
|
||||
|
||||
assert.Equal(t, "build123", maa.OSBuild)
|
||||
assert.Equal(t, "CustomOS", maa.OSType)
|
||||
assert.Equal(t, "DistroX", maa.OSDistro)
|
||||
}
|
||||
|
||||
func TestInitializeOSVars(t *testing.T) {
|
||||
cfg := &EnvConfig{}
|
||||
cfg.InitializeOSVars("buildX", "TypeY", "DistroZ")
|
||||
|
||||
assert.Equal(t, "buildX", cfg.OSBuild)
|
||||
assert.Equal(t, "TypeY", cfg.OSType)
|
||||
assert.Equal(t, "DistroZ", cfg.OSDistro)
|
||||
}
|
||||
@@ -116,6 +116,15 @@ func (a provider) VerifyAttestation(report []byte, teeNonce []byte, vTpmNonce []
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a provider) AzureAttestationToken(tokenNonce []byte) ([]byte, error) {
|
||||
quote, err := vtpm.FetchAzureAttestation(tokenNonce)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(vtpm.ErrFetchAzureToken, err)
|
||||
}
|
||||
|
||||
return quote, nil
|
||||
}
|
||||
|
||||
func GenerateAttestationPolicy(token string, product string, policy uint64, nonce []byte) (*attestation.Config, error) {
|
||||
claims, err := validateToken(token)
|
||||
if err != nil {
|
||||
|
||||
@@ -21,6 +21,10 @@ func (e *EmptyProvider) VTpmAttestation(vTpmNonce []byte) ([]byte, error) {
|
||||
return cocosai.EmbeddedAttestation, nil
|
||||
}
|
||||
|
||||
func (e *EmptyProvider) AzureAttestationToken(nonce []byte) ([]byte, error) {
|
||||
return cocosai.EmbeddedAttestation, nil
|
||||
}
|
||||
|
||||
func (e *EmptyProvider) VerifTeeAttestation(report []byte, teeNonce []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -79,6 +79,64 @@ func (_c *Provider_Attestation_Call) RunAndReturn(run func([]byte, []byte) ([]by
|
||||
return _c
|
||||
}
|
||||
|
||||
// AzureAttestationToken provides a mock function with given fields: tokenNonce
|
||||
func (_m *Provider) AzureAttestationToken(tokenNonce []byte) ([]byte, error) {
|
||||
ret := _m.Called(tokenNonce)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for AzureAttestationToken")
|
||||
}
|
||||
|
||||
var r0 []byte
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func([]byte) ([]byte, error)); ok {
|
||||
return rf(tokenNonce)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func([]byte) []byte); ok {
|
||||
r0 = rf(tokenNonce)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]byte)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func([]byte) error); ok {
|
||||
r1 = rf(tokenNonce)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// Provider_AzureAttestationToken_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AzureAttestationToken'
|
||||
type Provider_AzureAttestationToken_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// AzureAttestationToken is a helper method to define mock.On call
|
||||
// - tokenNonce []byte
|
||||
func (_e *Provider_Expecter) AzureAttestationToken(tokenNonce interface{}) *Provider_AzureAttestationToken_Call {
|
||||
return &Provider_AzureAttestationToken_Call{Call: _e.mock.On("AzureAttestationToken", tokenNonce)}
|
||||
}
|
||||
|
||||
func (_c *Provider_AzureAttestationToken_Call) Run(run func(tokenNonce []byte)) *Provider_AzureAttestationToken_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].([]byte))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_AzureAttestationToken_Call) Return(_a0 []byte, _a1 error) *Provider_AzureAttestationToken_Call {
|
||||
_c.Call.Return(_a0, _a1)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *Provider_AzureAttestationToken_Call) RunAndReturn(run func([]byte) ([]byte, error)) *Provider_AzureAttestationToken_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// TeeAttestation provides a mock function with given fields: teeNonce
|
||||
func (_m *Provider) TeeAttestation(teeNonce []byte) ([]byte, error) {
|
||||
ret := _m.Called(teeNonce)
|
||||
|
||||
@@ -5,16 +5,19 @@ package vtpm
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"crypto"
|
||||
"crypto/sha256"
|
||||
"crypto/sha512"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/absmach/magistrala/pkg/errors"
|
||||
"github.com/edgelesssys/go-azguestattestation/maa"
|
||||
"github.com/google/go-sev-guest/abi"
|
||||
"github.com/google/go-sev-guest/proto/sevsnp"
|
||||
"github.com/google/go-tpm-tools/client"
|
||||
@@ -42,9 +45,10 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
ExternalTPM io.ReadWriteCloser
|
||||
ErrNoHashAlgo = errors.New("hash algo is not supported")
|
||||
ErrFetchQuote = errors.New("failed to fetch vTPM quote")
|
||||
ExternalTPM io.ReadWriteCloser
|
||||
ErrNoHashAlgo = errors.New("hash algo is not supported")
|
||||
ErrFetchQuote = errors.New("failed to fetch vTPM quote")
|
||||
ErrFetchAzureToken = errors.New("failed to fetch Azure token")
|
||||
)
|
||||
|
||||
type tpm struct {
|
||||
@@ -142,6 +146,15 @@ func (v provider) VerifyAttestation(report []byte, teeNonce []byte, vTpmNonce []
|
||||
return VTPMVerify(report, v.pubKey, teeNonce, vTpmNonce, v.writer)
|
||||
}
|
||||
|
||||
func (v provider) AzureAttestationToken(tokenNonce []byte) ([]byte, error) {
|
||||
quote, err := FetchAzureAttestation(tokenNonce)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ErrFetchQuote, err)
|
||||
}
|
||||
|
||||
return quote, nil
|
||||
}
|
||||
|
||||
func Attest(teeNonce []byte, vTPMNonce []byte, teeAttestaion bool, vmpl uint) ([]byte, error) {
|
||||
attestation, err := FetchQuote(vTPMNonce)
|
||||
if err != nil {
|
||||
@@ -158,6 +171,14 @@ func Attest(teeNonce []byte, vTPMNonce []byte, teeAttestaion bool, vmpl uint) ([
|
||||
return marshalQuote(attestation)
|
||||
}
|
||||
|
||||
func FetchAzureAttestation(tokenNonce []byte) ([]byte, error) {
|
||||
token, err := maa.Attest(context.Background(), tokenNonce, os.Getenv("AgentMaaURL"), http.DefaultClient)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error fetching azure token: %w", err)
|
||||
}
|
||||
return []byte(token), nil
|
||||
}
|
||||
|
||||
func VTPMVerify(quote []byte, pubKeyTLS []byte, teeNonce []byte, vtpmNonce []byte, writer io.Writer) error {
|
||||
if err := VerifyQuote(quote, pubKeyTLS, vtpmNonce, writer); err != nil {
|
||||
return fmt.Errorf("failed to verify vTPM quote: %v", err)
|
||||
|
||||
@@ -28,6 +28,7 @@ type SDK interface {
|
||||
Result(ctx context.Context, privKey any, resultFile *os.File) error
|
||||
Attestation(ctx context.Context, reportData [size64]byte, nonce [size32]byte, attType int, attestationFile *os.File) error
|
||||
IMAMeasurements(ctx context.Context, resultFile *os.File) ([]byte, error)
|
||||
AttestationResult(ctx context.Context, nonce [size32]byte, attType int, attestationFile *os.File) error
|
||||
}
|
||||
|
||||
const (
|
||||
@@ -156,6 +157,25 @@ func (sdk *agentSDK) Attestation(ctx context.Context, reportData [size64]byte, n
|
||||
return pb.ReceiveAttestation(attestationProgressDescription, fileSize, stream, attestationFile)
|
||||
}
|
||||
|
||||
func (sdk *agentSDK) AttestationResult(ctx context.Context, nonce [size32]byte, attType int, attestationResultFile *os.File) error {
|
||||
request := &agent.AttestationResultRequest{
|
||||
TokenNonce: nonce[:],
|
||||
Type: int32(attType),
|
||||
}
|
||||
|
||||
result, err := sdk.client.AttestationResult(ctx, request)
|
||||
if err != nil {
|
||||
return errors.Wrap(errors.New("failed to fetch attestation token"), err)
|
||||
}
|
||||
|
||||
_, err = attestationResultFile.Write(result.GetFile())
|
||||
if err != nil {
|
||||
return errors.Wrap(errors.New("failed to write attestation result to file"), err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func signData(userID string, privKey crypto.Signer) ([]byte, error) {
|
||||
var signature []byte
|
||||
var err error
|
||||
|
||||
@@ -475,6 +475,89 @@ func TestAttestation(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestAttestationResult(t *testing.T) {
|
||||
reportData := make([]byte, 64)
|
||||
nonce := make([]byte, 64)
|
||||
report := []byte{
|
||||
0x01, 0x02, 0x03, 0x04,
|
||||
0x05, 0x06, 0x07, 0x08,
|
||||
}
|
||||
|
||||
conn, err := grpc.NewClient("passthrough://bufnet", grpc.WithTransportCredentials(insecure.NewCredentials()), grpc.WithContextDialer(bufDialer))
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to dial bufnet: %v", err)
|
||||
}
|
||||
defer conn.Close()
|
||||
|
||||
client := agent.NewAgentServiceClient(conn)
|
||||
|
||||
sdk := sdk.NewAgentSDK(client)
|
||||
|
||||
_, err = rand.Read(reportData)
|
||||
require.NoError(t, err)
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
nonce [vtpm.Nonce]byte
|
||||
response *agent.AttestationResultResponse
|
||||
svcRes []byte
|
||||
err error
|
||||
}{
|
||||
{
|
||||
name: "fetch attestation report successfully",
|
||||
nonce: [vtpm.Nonce]byte(nonce),
|
||||
response: &agent.AttestationResultResponse{
|
||||
File: report,
|
||||
},
|
||||
svcRes: report,
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
name: "failed to fetch attestation report",
|
||||
nonce: [vtpm.Nonce]byte(nonce),
|
||||
response: &agent.AttestationResultResponse{
|
||||
File: []byte{},
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
svcCall := svc.On("AttestationResult", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(tc.svcRes, tc.err)
|
||||
|
||||
file, err := os.CreateTemp("", "attestation")
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Cleanup(func() {
|
||||
os.Remove(file.Name())
|
||||
})
|
||||
|
||||
err = sdk.AttestationResult(context.Background(), tc.nonce, 0, file)
|
||||
|
||||
require.NoError(t, file.Close())
|
||||
|
||||
st, ok := status.FromError(err)
|
||||
if !ok {
|
||||
t.Fatalf("Expected gRPC status error, but got: %v", err)
|
||||
}
|
||||
|
||||
if tc.err != nil {
|
||||
if st.Message() != tc.err.Error() {
|
||||
t.Errorf("%s: Expected error message %q, but got %q", tc.name, tc.err.Error(), st.Message())
|
||||
}
|
||||
}
|
||||
|
||||
res, err := os.ReadFile(file.Name())
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, tc.response.File, res, tc.name)
|
||||
|
||||
svcCall.Unset()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func generateKeys(t *testing.T, keyType string) (priv any, pub []byte) {
|
||||
switch keyType {
|
||||
case "ecdsa":
|
||||
|
||||
@@ -124,6 +124,55 @@ func (_c *SDK_Attestation_Call) RunAndReturn(run func(context.Context, [64]byte,
|
||||
return _c
|
||||
}
|
||||
|
||||
// AttestationResult provides a mock function with given fields: ctx, nonce, attType, attestationFile
|
||||
func (_m *SDK) AttestationResult(ctx context.Context, nonce [32]byte, attType int, attestationFile *os.File) error {
|
||||
ret := _m.Called(ctx, nonce, attType, attestationFile)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for AttestationResult")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, [32]byte, int, *os.File) error); ok {
|
||||
r0 = rf(ctx, nonce, attType, attestationFile)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// SDK_AttestationResult_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'AttestationResult'
|
||||
type SDK_AttestationResult_Call struct {
|
||||
*mock.Call
|
||||
}
|
||||
|
||||
// AttestationResult is a helper method to define mock.On call
|
||||
// - ctx context.Context
|
||||
// - nonce [32]byte
|
||||
// - attType int
|
||||
// - attestationFile *os.File
|
||||
func (_e *SDK_Expecter) AttestationResult(ctx interface{}, nonce interface{}, attType interface{}, attestationFile interface{}) *SDK_AttestationResult_Call {
|
||||
return &SDK_AttestationResult_Call{Call: _e.mock.On("AttestationResult", ctx, nonce, attType, attestationFile)}
|
||||
}
|
||||
|
||||
func (_c *SDK_AttestationResult_Call) Run(run func(ctx context.Context, nonce [32]byte, attType int, attestationFile *os.File)) *SDK_AttestationResult_Call {
|
||||
_c.Call.Run(func(args mock.Arguments) {
|
||||
run(args[0].(context.Context), args[1].([32]byte), args[2].(int), args[3].(*os.File))
|
||||
})
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *SDK_AttestationResult_Call) Return(_a0 error) *SDK_AttestationResult_Call {
|
||||
_c.Call.Return(_a0)
|
||||
return _c
|
||||
}
|
||||
|
||||
func (_c *SDK_AttestationResult_Call) RunAndReturn(run func(context.Context, [32]byte, int, *os.File) error) *SDK_AttestationResult_Call {
|
||||
_c.Call.Return(run)
|
||||
return _c
|
||||
}
|
||||
|
||||
// Data provides a mock function with given fields: ctx, dataset, filename, privKey
|
||||
func (_m *SDK) Data(ctx context.Context, dataset *os.File, filename string, privKey interface{}) error {
|
||||
ret := _m.Called(ctx, dataset, filename, privKey)
|
||||
|
||||
Reference in New Issue
Block a user