diff --git a/.github/workflows/image_rs_build.yml b/.github/workflows/image_rs_build.yml index 4f9423bd7..574f525bc 100644 --- a/.github/workflows/image_rs_build.yml +++ b/.github/workflows/image_rs_build.yml @@ -121,21 +121,21 @@ jobs: run: | sudo -E PATH=$PATH -s cargo test -p image-rs --features default - - name: Run cargo test - kata-cc (rust-tls version) with keywrap-grpc + keywrap-jwe + - name: Run cargo test - kata-cc (rust-tls version) with keywrap-grpc + keywrap-jwe + runtime-attestation-grpc run: | - sudo -E PATH=$PATH -s cargo test -p image-rs --no-default-features --features=encryption-ring,keywrap-grpc,snapshot-overlayfs,signature-cosign-rustls,signature-simple,getresource,oci-distribution/rustls-tls,keywrap-jwe + sudo -E PATH=$PATH -s cargo test -p image-rs --no-default-features --features=encryption-ring,keywrap-grpc,snapshot-overlayfs,signature-cosign-rustls,signature-simple,getresource,oci-distribution/rustls-tls,keywrap-jwe,runtime-attestation-grpc - - name: Run cargo test - kata-cc (native-tls version) with keywrap-grpc + keywrap-jwe + - name: Run cargo test - kata-cc (native-tls version) with keywrap-grpc + keywrap-jwe + runtime-attestation-grpc run: | - sudo -E PATH=$PATH -s cargo test -p image-rs --no-default-features --features=encryption-openssl,keywrap-grpc,snapshot-overlayfs,signature-cosign-native,signature-simple,getresource,oci-distribution/native-tls,keywrap-jwe + sudo -E PATH=$PATH -s cargo test -p image-rs --no-default-features --features=encryption-openssl,keywrap-grpc,snapshot-overlayfs,signature-cosign-native,signature-simple,getresource,oci-distribution/native-tls,keywrap-jwe,runtime-attestation-grpc - - name: Run cargo test - kata-cc (rust-tls version) with keywrap-ttrpc (default) + keywrap-jwe + - name: Run cargo test - kata-cc (rust-tls version) with keywrap-ttrpc (default) + keywrap-jwe + runtime-attestation-ttrpc run: | - sudo -E PATH=$PATH -s cargo test -p image-rs --no-default-features --features=kata-cc-rustls-tls,keywrap-jwe + sudo -E PATH=$PATH -s cargo test -p image-rs --no-default-features --features=kata-cc-rustls-tls,keywrap-jwe,runtime-attestation-ttrpc - - name: Run cargo test - kata-cc (native-tls version) with keywrap-ttrpc (default) + keywrap-jwe + - name: Run cargo test - kata-cc (native-tls version) with keywrap-ttrpc (default) + keywrap-jwe + runtime-attestation-ttrpc run: | - sudo -E PATH=$PATH -s cargo test -p image-rs --no-default-features --features=kata-cc-native-tls,keywrap-jwe + sudo -E PATH=$PATH -s cargo test -p image-rs --no-default-features --features=kata-cc-native-tls,keywrap-jwe,runtime-attestation-ttrpc - name: Clean test cache run: | diff --git a/image-rs/Cargo.toml b/image-rs/Cargo.toml index 588fd6072..95d810984 100644 --- a/image-rs/Cargo.toml +++ b/image-rs/Cargo.toml @@ -197,3 +197,7 @@ getresource = ["lazy_static", "cfg-if"] nydus = ["lazy_static", "nydus-api", "nydus-service"] verity = ["devicemapper"] + +runtime-attestation = ["lazy_static", "cfg-if"] +runtime-attestation-ttrpc = ["dep:ttrpc", "dep:protobuf", "ttrpc-codegen", "runtime-attestation"] +runtime-attestation-grpc = ["prost", "tonic", "tonic-build", "runtime-attestation"] diff --git a/image-rs/build.rs b/image-rs/build.rs index 2d4bfcac1..eb0859aee 100644 --- a/image-rs/build.rs +++ b/image-rs/build.rs @@ -9,6 +9,12 @@ fn main() -> Result<()> { #[cfg(feature = "tonic-build")] tonic_build::compile_protos("./protos/getresource.proto").context("tonic build")?; + #[cfg(feature = "tonic-build")] + tonic_build::configure() + .build_server(true) + .protoc_arg("--experimental_allow_proto3_optional") + .compile(&["./protos/attestation-agent.proto"], &["./protos"])?; + #[cfg(feature = "ttrpc-codegen")] ttrpc_codegen::Codegen::new() .out_dir("./src/resource/kbs/ttrpc_proto") @@ -23,5 +29,19 @@ fn main() -> Result<()> { .run() .context("ttrpc build")?; + #[cfg(feature = "ttrpc-codegen")] + ttrpc_codegen::Codegen::new() + .out_dir("./src/runtime_attestation/ttrpc_proto") + .input("./protos/attestation-agent.proto") + .include("./protos") + .rust_protobuf() + .customize(ttrpc_codegen::Customize { + async_all: true, + ..Default::default() + }) + .rust_protobuf_customize(ttrpc_codegen::ProtobufCustomize::default().gen_mod_rs(false)) + .run() + .context("ttrpc build")?; + Ok(()) } diff --git a/image-rs/protos/attestation-agent.proto b/image-rs/protos/attestation-agent.proto new file mode 100644 index 000000000..6ddd20f15 --- /dev/null +++ b/image-rs/protos/attestation-agent.proto @@ -0,0 +1,25 @@ +syntax = "proto3"; + +package attestation_agent; + +// Extend the dynamic/runtime measurement with given materials. This would change the state +// of current TEE's status, e.g. TDX's RTMR, (v)TPM's PCR, by adding a record in eventlog. +message ExtendRuntimeMeasurementRequest { + // The domain to which this event entry belongs. This domain is used to distinguish the semantics of log entries in different contexts. + string Domain = 1; + + // Concrete operation type that this event entry records. + string Operation = 2; + + // Detailed content of the operation that this event entry records. + string Content = 3; + + // Which PCR will be extended with the hash of this entry. + optional uint64 RegisterIndex = 4; +} + +message ExtendRuntimeMeasurementResponse {} + +service AttestationAgentService { + rpc ExtendRuntimeMeasurement(ExtendRuntimeMeasurementRequest) returns (ExtendRuntimeMeasurementResponse) {}; +} diff --git a/image-rs/src/image.rs b/image-rs/src/image.rs index e47e3d6bf..591b005cd 100644 --- a/image-rs/src/image.rs +++ b/image-rs/src/image.rs @@ -29,6 +29,9 @@ use crate::snapshots::overlay::OverlayFs; #[cfg(feature = "nydus")] use crate::nydus::{service, utils}; +#[cfg(feature = "runtime-attestation")] +use crate::runtime_attestation; + /// Image security config dir contains important information such as /// security policy configuration file and signature verification configuration file. /// Therefore, it is necessary to ensure that the directory is stored in a safe place. @@ -241,13 +244,29 @@ impl ImageClient { }; let mut client = PullClient::new( - reference, + reference.clone(), &self.config.work_dir.join("layers"), &auth, self.config.max_concurrent_download, )?; let (image_manifest, image_digest, image_config) = client.pull_manifest().await?; + #[cfg(feature = "runtime-attestation")] + if let Err(e) = runtime_attestation::extend_runtime_measurement( + "image-rs", + "pull_image", + &format!( + "{}/{}@{}", + reference.registry(), + reference.repository(), + image_digest + ), + ) + .await + { + log::warn!("Failed to extend_runtime_measurement {:?}", e); + } + let id = image_manifest.config.digest.clone(); let snapshot = match self.snapshots.get_mut(&self.config.default_snapshot) { diff --git a/image-rs/src/lib.rs b/image-rs/src/lib.rs index 1996d2514..7b55654f1 100644 --- a/image-rs/src/lib.rs +++ b/image-rs/src/lib.rs @@ -16,6 +16,8 @@ pub mod meta_store; pub mod nydus; pub mod pull; pub mod resource; +#[cfg(feature = "runtime-attestation")] +pub mod runtime_attestation; #[cfg(feature = "signature")] pub mod signature; pub mod snapshots; diff --git a/image-rs/src/runtime_attestation/grpc.rs b/image-rs/src/runtime_attestation/grpc.rs new file mode 100644 index 000000000..085b8b619 --- /dev/null +++ b/image-rs/src/runtime_attestation/grpc.rs @@ -0,0 +1,56 @@ +// Copyright (c) 2024 Intel +// +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::*; +use async_trait::async_trait; + +use tonic::transport::Channel; + +use super::Client; + +use self::attestation_agent::{ + attestation_agent_service_client::AttestationAgentServiceClient, + ExtendRuntimeMeasurementRequest, +}; + +mod attestation_agent { + #![allow(unknown_lints)] + #![allow(clippy::derive_partial_eq_without_eq)] + #![allow(clippy::redundant_async_block)] + tonic::include_proto!("attestation_agent"); +} + +pub const AA_ADDR: &str = "http://127.0.0.1:50002"; + +pub struct Grpc { + inner: AttestationAgentServiceClient, +} + +impl Grpc { + pub async fn new() -> Result { + let inner = AttestationAgentServiceClient::connect(AA_ADDR).await?; + Ok(Self { inner }) + } +} + +#[async_trait] +impl Client for Grpc { + async fn extend_runtime_measurement( + &mut self, + domain: &str, + operation: &str, + content: &str, + ) -> Result<()> { + let req = tonic::Request::new(ExtendRuntimeMeasurementRequest { + domain: domain.to_string(), + operation: operation.to_string(), + content: content.to_string(), + ..Default::default() + }); + + self.inner.extend_runtime_measurement(req).await?; + + Ok(()) + } +} diff --git a/image-rs/src/runtime_attestation/mod.rs b/image-rs/src/runtime_attestation/mod.rs new file mode 100644 index 000000000..32dd1e6c9 --- /dev/null +++ b/image-rs/src/runtime_attestation/mod.rs @@ -0,0 +1,84 @@ +// Copyright (c) 2024 Intel +// +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::*; +use async_trait::async_trait; +use log::{info, warn}; +use std::result::Result::Ok; +use tokio::sync::{Mutex, OnceCell}; + +#[cfg(feature = "runtime-attestation-grpc")] +mod grpc; + +#[cfg(feature = "runtime-attestation-ttrpc")] +mod ttrpc; + +#[cfg(feature = "runtime-attestation-ttrpc")] +mod ttrpc_proto; + +static RUNTIME_MEASUREMENT: OnceCell>> = OnceCell::const_new(); + +pub struct RuntimeMeasurement { + client: Box, +} + +#[async_trait] +trait Client: Send + Sync { + async fn extend_runtime_measurement( + &mut self, + domain: &str, + operation: &str, + content: &str, + ) -> Result<()>; +} + +impl RuntimeMeasurement { + pub async fn new() -> Result { + let client: Box = { + cfg_if::cfg_if! { + if #[cfg(feature = "runtime-attestation-ttrpc")] { + info!("runtime-attestation uses ttrpc"); + Box::new(ttrpc::Ttrpc::new().context("ttrpc client init failed")?) + } else if #[cfg(feature = "runtime-attestation-grpc")] { + info!("runtime-attestation uses grpc"); + Box::new(grpc::Grpc::new().await.context("grpc client init failed")?) + } else { + compile_error!("`runtime-attestation-ttrpc` or `runtime-attestation-grpc` must be enabled."); + } + } + }; + + Ok(Self { client }) + } +} + +async fn get_runtime_measurement() -> Mutex> { + match RuntimeMeasurement::new().await { + Ok(runtime_measurement) => Mutex::new(Some(runtime_measurement)), + Err(err) => { + warn!("Failed to initialize runtime measurement: {:?}", err); + Mutex::new(None) + } + } +} + +pub async fn extend_runtime_measurement( + domain: &str, + operation: &str, + content: &str, +) -> Result<()> { + RUNTIME_MEASUREMENT + .get_or_init(get_runtime_measurement) + .await + .lock() + .await + .as_mut() + .ok_or_else(|| anyhow!("Uninitialized runtime measurement"))? + .client + .extend_runtime_measurement(domain, operation, content) + .await + .map_err(|e| anyhow!("Failed to extend runtime measurement: {:?}", e))?; + + Ok(()) +} diff --git a/image-rs/src/runtime_attestation/ttrpc.rs b/image-rs/src/runtime_attestation/ttrpc.rs new file mode 100644 index 000000000..822bddca7 --- /dev/null +++ b/image-rs/src/runtime_attestation/ttrpc.rs @@ -0,0 +1,48 @@ +// Copyright (c) 2024 Intel +// +// SPDX-License-Identifier: Apache-2.0 + +use anyhow::*; +use async_trait::async_trait; + +use super::ttrpc_proto::attestation_agent::ExtendRuntimeMeasurementRequest; +use super::ttrpc_proto::attestation_agent_ttrpc::AttestationAgentServiceClient; +use super::Client; +use ttrpc::context; + +const SOCKET_ADDR: &str = + "unix:///run/confidential-containers/attestation-agent/attestation-agent.sock"; + +pub struct Ttrpc { + client: AttestationAgentServiceClient, +} + +impl Ttrpc { + pub fn new() -> Result { + let inner = ttrpc::asynchronous::Client::connect(SOCKET_ADDR)?; + let client = AttestationAgentServiceClient::new(inner); + Ok(Self { client }) + } +} + +#[async_trait] +impl Client for Ttrpc { + async fn extend_runtime_measurement( + &mut self, + domain: &str, + operation: &str, + content: &str, + ) -> Result<()> { + let req = ExtendRuntimeMeasurementRequest { + Domain: domain.to_string(), + Operation: operation.to_string(), + Content: content.to_string(), + ..Default::default() + }; + self.client + .extend_runtime_measurement(context::with_timeout(50 * 1000 * 1000 * 1000), &req) + .await + .map_err(|e| anyhow!("extend runtime measurement ttrpc error: {:?}", e))?; + Ok(()) + } +} diff --git a/image-rs/src/runtime_attestation/ttrpc_proto/attestation_agent.rs b/image-rs/src/runtime_attestation/ttrpc_proto/attestation_agent.rs new file mode 100644 index 000000000..e90ea477c --- /dev/null +++ b/image-rs/src/runtime_attestation/ttrpc_proto/attestation_agent.rs @@ -0,0 +1,347 @@ +// This file is generated by rust-protobuf 3.5.0. Do not edit +// .proto file is parsed by pure +// @generated + +// https://github.com/rust-lang/rust-clippy/issues/702 +#![allow(unknown_lints)] +#![allow(clippy::all)] + +#![allow(unused_attributes)] +#![cfg_attr(rustfmt, rustfmt::skip)] + +#![allow(box_pointers)] +#![allow(dead_code)] +#![allow(missing_docs)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(trivial_casts)] +#![allow(unused_results)] +#![allow(unused_mut)] + +//! Generated file from `attestation-agent.proto` + +/// Generated files are compatible only with the same version +/// of protobuf runtime. +const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_3_5_0; + +// @@protoc_insertion_point(message:attestation_agent.ExtendRuntimeMeasurementRequest) +#[derive(PartialEq,Clone,Default,Debug)] +pub struct ExtendRuntimeMeasurementRequest { + // message fields + // @@protoc_insertion_point(field:attestation_agent.ExtendRuntimeMeasurementRequest.Domain) + pub Domain: ::std::string::String, + // @@protoc_insertion_point(field:attestation_agent.ExtendRuntimeMeasurementRequest.Operation) + pub Operation: ::std::string::String, + // @@protoc_insertion_point(field:attestation_agent.ExtendRuntimeMeasurementRequest.Content) + pub Content: ::std::string::String, + // @@protoc_insertion_point(field:attestation_agent.ExtendRuntimeMeasurementRequest.RegisterIndex) + pub RegisterIndex: ::std::option::Option, + // special fields + // @@protoc_insertion_point(special_field:attestation_agent.ExtendRuntimeMeasurementRequest.special_fields) + pub special_fields: ::protobuf::SpecialFields, +} + +impl<'a> ::std::default::Default for &'a ExtendRuntimeMeasurementRequest { + fn default() -> &'a ExtendRuntimeMeasurementRequest { + ::default_instance() + } +} + +impl ExtendRuntimeMeasurementRequest { + pub fn new() -> ExtendRuntimeMeasurementRequest { + ::std::default::Default::default() + } + + fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { + let mut fields = ::std::vec::Vec::with_capacity(4); + let mut oneofs = ::std::vec::Vec::with_capacity(0); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "Domain", + |m: &ExtendRuntimeMeasurementRequest| { &m.Domain }, + |m: &mut ExtendRuntimeMeasurementRequest| { &mut m.Domain }, + )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "Operation", + |m: &ExtendRuntimeMeasurementRequest| { &m.Operation }, + |m: &mut ExtendRuntimeMeasurementRequest| { &mut m.Operation }, + )); + fields.push(::protobuf::reflect::rt::v2::make_simpler_field_accessor::<_, _>( + "Content", + |m: &ExtendRuntimeMeasurementRequest| { &m.Content }, + |m: &mut ExtendRuntimeMeasurementRequest| { &mut m.Content }, + )); + fields.push(::protobuf::reflect::rt::v2::make_option_accessor::<_, _>( + "RegisterIndex", + |m: &ExtendRuntimeMeasurementRequest| { &m.RegisterIndex }, + |m: &mut ExtendRuntimeMeasurementRequest| { &mut m.RegisterIndex }, + )); + ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( + "ExtendRuntimeMeasurementRequest", + fields, + oneofs, + ) + } +} + +impl ::protobuf::Message for ExtendRuntimeMeasurementRequest { + const NAME: &'static str = "ExtendRuntimeMeasurementRequest"; + + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { + while let Some(tag) = is.read_raw_tag_or_eof()? { + match tag { + 10 => { + self.Domain = is.read_string()?; + }, + 18 => { + self.Operation = is.read_string()?; + }, + 26 => { + self.Content = is.read_string()?; + }, + 32 => { + self.RegisterIndex = ::std::option::Option::Some(is.read_uint64()?); + }, + tag => { + ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u64 { + let mut my_size = 0; + if !self.Domain.is_empty() { + my_size += ::protobuf::rt::string_size(1, &self.Domain); + } + if !self.Operation.is_empty() { + my_size += ::protobuf::rt::string_size(2, &self.Operation); + } + if !self.Content.is_empty() { + my_size += ::protobuf::rt::string_size(3, &self.Content); + } + if let Some(v) = self.RegisterIndex { + my_size += ::protobuf::rt::uint64_size(4, v); + } + my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); + self.special_fields.cached_size().set(my_size as u32); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { + if !self.Domain.is_empty() { + os.write_string(1, &self.Domain)?; + } + if !self.Operation.is_empty() { + os.write_string(2, &self.Operation)?; + } + if !self.Content.is_empty() { + os.write_string(3, &self.Content)?; + } + if let Some(v) = self.RegisterIndex { + os.write_uint64(4, v)?; + } + os.write_unknown_fields(self.special_fields.unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn special_fields(&self) -> &::protobuf::SpecialFields { + &self.special_fields + } + + fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { + &mut self.special_fields + } + + fn new() -> ExtendRuntimeMeasurementRequest { + ExtendRuntimeMeasurementRequest::new() + } + + fn clear(&mut self) { + self.Domain.clear(); + self.Operation.clear(); + self.Content.clear(); + self.RegisterIndex = ::std::option::Option::None; + self.special_fields.clear(); + } + + fn default_instance() -> &'static ExtendRuntimeMeasurementRequest { + static instance: ExtendRuntimeMeasurementRequest = ExtendRuntimeMeasurementRequest { + Domain: ::std::string::String::new(), + Operation: ::std::string::String::new(), + Content: ::std::string::String::new(), + RegisterIndex: ::std::option::Option::None, + special_fields: ::protobuf::SpecialFields::new(), + }; + &instance + } +} + +impl ::protobuf::MessageFull for ExtendRuntimeMeasurementRequest { + fn descriptor() -> ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); + descriptor.get(|| file_descriptor().message_by_package_relative_name("ExtendRuntimeMeasurementRequest").unwrap()).clone() + } +} + +impl ::std::fmt::Display for ExtendRuntimeMeasurementRequest { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for ExtendRuntimeMeasurementRequest { + type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; +} + +// @@protoc_insertion_point(message:attestation_agent.ExtendRuntimeMeasurementResponse) +#[derive(PartialEq,Clone,Default,Debug)] +pub struct ExtendRuntimeMeasurementResponse { + // special fields + // @@protoc_insertion_point(special_field:attestation_agent.ExtendRuntimeMeasurementResponse.special_fields) + pub special_fields: ::protobuf::SpecialFields, +} + +impl<'a> ::std::default::Default for &'a ExtendRuntimeMeasurementResponse { + fn default() -> &'a ExtendRuntimeMeasurementResponse { + ::default_instance() + } +} + +impl ExtendRuntimeMeasurementResponse { + pub fn new() -> ExtendRuntimeMeasurementResponse { + ::std::default::Default::default() + } + + fn generated_message_descriptor_data() -> ::protobuf::reflect::GeneratedMessageDescriptorData { + let mut fields = ::std::vec::Vec::with_capacity(0); + let mut oneofs = ::std::vec::Vec::with_capacity(0); + ::protobuf::reflect::GeneratedMessageDescriptorData::new_2::( + "ExtendRuntimeMeasurementResponse", + fields, + oneofs, + ) + } +} + +impl ::protobuf::Message for ExtendRuntimeMeasurementResponse { + const NAME: &'static str = "ExtendRuntimeMeasurementResponse"; + + fn is_initialized(&self) -> bool { + true + } + + fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::Result<()> { + while let Some(tag) = is.read_raw_tag_or_eof()? { + match tag { + tag => { + ::protobuf::rt::read_unknown_or_skip_group(tag, is, self.special_fields.mut_unknown_fields())?; + }, + }; + } + ::std::result::Result::Ok(()) + } + + // Compute sizes of nested messages + #[allow(unused_variables)] + fn compute_size(&self) -> u64 { + let mut my_size = 0; + my_size += ::protobuf::rt::unknown_fields_size(self.special_fields.unknown_fields()); + self.special_fields.cached_size().set(my_size as u32); + my_size + } + + fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::Result<()> { + os.write_unknown_fields(self.special_fields.unknown_fields())?; + ::std::result::Result::Ok(()) + } + + fn special_fields(&self) -> &::protobuf::SpecialFields { + &self.special_fields + } + + fn mut_special_fields(&mut self) -> &mut ::protobuf::SpecialFields { + &mut self.special_fields + } + + fn new() -> ExtendRuntimeMeasurementResponse { + ExtendRuntimeMeasurementResponse::new() + } + + fn clear(&mut self) { + self.special_fields.clear(); + } + + fn default_instance() -> &'static ExtendRuntimeMeasurementResponse { + static instance: ExtendRuntimeMeasurementResponse = ExtendRuntimeMeasurementResponse { + special_fields: ::protobuf::SpecialFields::new(), + }; + &instance + } +} + +impl ::protobuf::MessageFull for ExtendRuntimeMeasurementResponse { + fn descriptor() -> ::protobuf::reflect::MessageDescriptor { + static descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::Lazy::new(); + descriptor.get(|| file_descriptor().message_by_package_relative_name("ExtendRuntimeMeasurementResponse").unwrap()).clone() + } +} + +impl ::std::fmt::Display for ExtendRuntimeMeasurementResponse { + fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + ::protobuf::text_format::fmt(self, f) + } +} + +impl ::protobuf::reflect::ProtobufValue for ExtendRuntimeMeasurementResponse { + type RuntimeType = ::protobuf::reflect::rt::RuntimeTypeMessage; +} + +static file_descriptor_proto_data: &'static [u8] = b"\ + \n\x17attestation-agent.proto\x12\x11attestation_agent\"\xae\x01\n\x1fEx\ + tendRuntimeMeasurementRequest\x12\x16\n\x06Domain\x18\x01\x20\x01(\tR\ + \x06Domain\x12\x1c\n\tOperation\x18\x02\x20\x01(\tR\tOperation\x12\x18\n\ + \x07Content\x18\x03\x20\x01(\tR\x07Content\x12)\n\rRegisterIndex\x18\x04\ + \x20\x01(\x04H\0R\rRegisterIndex\x88\x01\x01B\x10\n\x0e_RegisterIndex\"\ + \"\n\x20ExtendRuntimeMeasurementResponse2\x9f\x01\n\x17AttestationAgentS\ + ervice\x12\x83\x01\n\x18ExtendRuntimeMeasurement\x122.attestation_agent.\ + ExtendRuntimeMeasurementRequest\x1a3.attestation_agent.ExtendRuntimeMeas\ + urementResponseb\x06proto3\ +"; + +/// `FileDescriptorProto` object which was a source for this generated file +fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto { + static file_descriptor_proto_lazy: ::protobuf::rt::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::Lazy::new(); + file_descriptor_proto_lazy.get(|| { + ::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap() + }) +} + +/// `FileDescriptor` object which allows dynamic access to files +pub fn file_descriptor() -> &'static ::protobuf::reflect::FileDescriptor { + static generated_file_descriptor_lazy: ::protobuf::rt::Lazy<::protobuf::reflect::GeneratedFileDescriptor> = ::protobuf::rt::Lazy::new(); + static file_descriptor: ::protobuf::rt::Lazy<::protobuf::reflect::FileDescriptor> = ::protobuf::rt::Lazy::new(); + file_descriptor.get(|| { + let generated_file_descriptor = generated_file_descriptor_lazy.get(|| { + let mut deps = ::std::vec::Vec::with_capacity(0); + let mut messages = ::std::vec::Vec::with_capacity(2); + messages.push(ExtendRuntimeMeasurementRequest::generated_message_descriptor_data()); + messages.push(ExtendRuntimeMeasurementResponse::generated_message_descriptor_data()); + let mut enums = ::std::vec::Vec::with_capacity(0); + ::protobuf::reflect::GeneratedFileDescriptor::new_generated( + file_descriptor_proto(), + deps, + messages, + enums, + ) + }); + ::protobuf::reflect::FileDescriptor::new_generated_2(generated_file_descriptor) + }) +} diff --git a/image-rs/src/runtime_attestation/ttrpc_proto/attestation_agent_ttrpc.rs b/image-rs/src/runtime_attestation/ttrpc_proto/attestation_agent_ttrpc.rs new file mode 100644 index 000000000..99c2f88a4 --- /dev/null +++ b/image-rs/src/runtime_attestation/ttrpc_proto/attestation_agent_ttrpc.rs @@ -0,0 +1,69 @@ +// This file is generated by ttrpc-compiler 0.6.2. Do not edit +// @generated + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unknown_lints)] +#![allow(clipto_camel_casepy)] +#![allow(box_pointers)] +#![allow(dead_code)] +#![allow(missing_docs)] +#![allow(non_camel_case_types)] +#![allow(non_snake_case)] +#![allow(non_upper_case_globals)] +#![allow(trivial_casts)] +#![allow(unsafe_code)] +#![allow(unused_imports)] +#![allow(unused_results)] +#![allow(clippy::all)] +use protobuf::{CodedInputStream, CodedOutputStream, Message}; +use std::collections::HashMap; +use std::sync::Arc; +use async_trait::async_trait; + +#[derive(Clone)] +pub struct AttestationAgentServiceClient { + client: ::ttrpc::r#async::Client, +} + +impl AttestationAgentServiceClient { + pub fn new(client: ::ttrpc::r#async::Client) -> Self { + AttestationAgentServiceClient { + client: client, + } + } + + pub async fn extend_runtime_measurement(&self, ctx: ttrpc::context::Context, req: &super::attestation_agent::ExtendRuntimeMeasurementRequest) -> ::ttrpc::Result { + let mut cres = super::attestation_agent::ExtendRuntimeMeasurementResponse::new(); + ::ttrpc::async_client_request!(self, ctx, req, "attestation_agent.AttestationAgentService", "ExtendRuntimeMeasurement", cres); + } +} + +struct ExtendRuntimeMeasurementMethod { + service: Arc>, +} + +#[async_trait] +impl ::ttrpc::r#async::MethodHandler for ExtendRuntimeMeasurementMethod { + async fn handler(&self, ctx: ::ttrpc::r#async::TtrpcContext, req: ::ttrpc::Request) -> ::ttrpc::Result<::ttrpc::Response> { + ::ttrpc::async_request_handler!(self, ctx, req, attestation_agent, ExtendRuntimeMeasurementRequest, extend_runtime_measurement); + } +} + +#[async_trait] +pub trait AttestationAgentService: Sync { + async fn extend_runtime_measurement(&self, _ctx: &::ttrpc::r#async::TtrpcContext, _: super::attestation_agent::ExtendRuntimeMeasurementRequest) -> ::ttrpc::Result { + Err(::ttrpc::Error::RpcStatus(::ttrpc::get_status(::ttrpc::Code::NOT_FOUND, "/attestation_agent.AttestationAgentService/ExtendRuntimeMeasurement is not supported".to_string()))) + } +} + +pub fn create_attestation_agent_service(service: Arc>) -> HashMap { + let mut ret = HashMap::new(); + let mut methods = HashMap::new(); + let streams = HashMap::new(); + + methods.insert("ExtendRuntimeMeasurement".to_string(), + Box::new(ExtendRuntimeMeasurementMethod{service: service.clone()}) as Box); + + ret.insert("attestation_agent.AttestationAgentService".to_string(), ::ttrpc::r#async::Service{ methods, streams }); + ret +} diff --git a/image-rs/src/runtime_attestation/ttrpc_proto/mod.rs b/image-rs/src/runtime_attestation/ttrpc_proto/mod.rs new file mode 100644 index 000000000..fba6b7831 --- /dev/null +++ b/image-rs/src/runtime_attestation/ttrpc_proto/mod.rs @@ -0,0 +1,7 @@ +// Copyright (c) 2024 Intel +// +// SPDX-License-Identifier: Apache-2.0 + +#![allow(clippy::redundant_field_names)] +pub mod attestation_agent; +pub mod attestation_agent_ttrpc;