diff --git a/Cargo.lock b/Cargo.lock index 15a76aa2324..d11a8c82896 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1368,9 +1368,11 @@ dependencies = [ "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "oak_runtime 0.1.0", "prost 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "signal-hook 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "simple_logger 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "tonic 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/docs/programming-oak.md b/docs/programming-oak.md index 3fcb997726c..fae9f2652d6 100644 --- a/docs/programming-oak.md +++ b/docs/programming-oak.md @@ -237,8 +237,6 @@ node_configs { name: "grpc-server" grpc_server_config { address: "[::]:8080" - grpc_tls_private_key: "" - grpc_tls_certificate: "" } } node_configs { @@ -531,7 +529,6 @@ to configure and run the Runtime. FRONTEND_ENTRYPOINT_NAME, ); - let (runtime, entry_channel) = - oak_runtime::configure_and_run(configuration, oak_runtime::RuntimeConfiguration::default()) + let (runtime, entry_channel) = oak_runtime::configure_and_run( ``` diff --git a/examples/abitest/config/config.textproto b/examples/abitest/config/config.textproto index c219504bf7d..c89318b3490 100644 --- a/examples/abitest/config/config.textproto +++ b/examples/abitest/config/config.textproto @@ -30,15 +30,12 @@ node_configs { name: "grpc-server" grpc_server_config { address: "[::]:8080" - grpc_tls_private_key: "" - grpc_tls_certificate: "" } } node_configs { name: "grpc-client" grpc_client_config { uri: "https://localhost:7878" - root_tls_certificate: "" address: "localhost:7878" } } @@ -46,7 +43,6 @@ node_configs { name: "absent-grpc-client" grpc_client_config { uri: "https://test.invalid:9999" - root_tls_certificate: "" address: "test.invalid:9999" } } diff --git a/examples/abitest/tests/src/tests.rs b/examples/abitest/tests/src/tests.rs index 62b71cbd86e..9a2eb06c01b 100644 --- a/examples/abitest/tests/src/tests.rs +++ b/examples/abitest/tests/src/tests.rs @@ -52,9 +52,12 @@ fn test_abi() { FRONTEND_ENTRYPOINT_NAME, ); - let (runtime, entry_channel) = - oak_runtime::configure_and_run(configuration, oak_runtime::RuntimeConfiguration::default()) - .expect("unable to configure runtime with test wasm"); + let (runtime, entry_channel) = oak_runtime::configure_and_run( + configuration, + oak_runtime::RuntimeConfiguration::default(), + oak_runtime::GrpcConfiguration::default(), + ) + .expect("unable to configure runtime with test wasm"); // TODO(#540): reinstate storage, gRPC client and Roughtime tests when Rust // runtime supports them. diff --git a/examples/aggregator/config/config.textproto b/examples/aggregator/config/config.textproto index 9931f1024cd..889873275da 100644 --- a/examples/aggregator/config/config.textproto +++ b/examples/aggregator/config/config.textproto @@ -8,15 +8,12 @@ node_configs { name: "grpc-server" grpc_server_config { address: "[::]:8080" - grpc_tls_private_key: "" - grpc_tls_certificate: "" } } node_configs { name: "grpc-client" grpc_client_config { uri: "https://localhost:8888" - root_tls_certificate: "" address: "127.0.0.1:8888" } } diff --git a/examples/chat/config/config.textproto b/examples/chat/config/config.textproto index 5b36a5a5da0..42f8fd33c31 100644 --- a/examples/chat/config/config.textproto +++ b/examples/chat/config/config.textproto @@ -8,8 +8,6 @@ node_configs { name: "grpc-server" grpc_server_config { address: "[::]:8080" - grpc_tls_private_key: "" - grpc_tls_certificate: "" } } node_configs { diff --git a/examples/hello_world/config/config.textproto b/examples/hello_world/config/config.textproto index 68a58a4e964..e1331612a7b 100644 --- a/examples/hello_world/config/config.textproto +++ b/examples/hello_world/config/config.textproto @@ -14,8 +14,6 @@ node_configs { name: "grpc-server" grpc_server_config { address: "[::]:8080" - grpc_tls_private_key: "" - grpc_tls_certificate: "" } } node_configs { diff --git a/examples/machine_learning/config/config.textproto b/examples/machine_learning/config/config.textproto index 5b36a5a5da0..42f8fd33c31 100644 --- a/examples/machine_learning/config/config.textproto +++ b/examples/machine_learning/config/config.textproto @@ -8,8 +8,6 @@ node_configs { name: "grpc-server" grpc_server_config { address: "[::]:8080" - grpc_tls_private_key: "" - grpc_tls_certificate: "" } } node_configs { diff --git a/examples/private_set_intersection/config/config.textproto b/examples/private_set_intersection/config/config.textproto index 5b36a5a5da0..42f8fd33c31 100644 --- a/examples/private_set_intersection/config/config.textproto +++ b/examples/private_set_intersection/config/config.textproto @@ -8,8 +8,6 @@ node_configs { name: "grpc-server" grpc_server_config { address: "[::]:8080" - grpc_tls_private_key: "" - grpc_tls_certificate: "" } } node_configs { diff --git a/examples/running_average/config/config.textproto b/examples/running_average/config/config.textproto index 5b36a5a5da0..42f8fd33c31 100644 --- a/examples/running_average/config/config.textproto +++ b/examples/running_average/config/config.textproto @@ -8,8 +8,6 @@ node_configs { name: "grpc-server" grpc_server_config { address: "[::]:8080" - grpc_tls_private_key: "" - grpc_tls_certificate: "" } } node_configs { diff --git a/examples/rustfmt/config/config.textproto b/examples/rustfmt/config/config.textproto index 5b36a5a5da0..42f8fd33c31 100644 --- a/examples/rustfmt/config/config.textproto +++ b/examples/rustfmt/config/config.textproto @@ -8,8 +8,6 @@ node_configs { name: "grpc-server" grpc_server_config { address: "[::]:8080" - grpc_tls_private_key: "" - grpc_tls_certificate: "" } } node_configs { diff --git a/examples/tensorflow/config/config.textproto b/examples/tensorflow/config/config.textproto index 8549e9fb3a2..fb1cc47697c 100644 --- a/examples/tensorflow/config/config.textproto +++ b/examples/tensorflow/config/config.textproto @@ -8,8 +8,6 @@ node_configs { name: "grpc-server" grpc_server_config { address: "[::]:8080" - grpc_tls_private_key: "" - grpc_tls_certificate: "" } } node_configs { diff --git a/examples/translator/config/config.textproto b/examples/translator/config/config.textproto index 5b36a5a5da0..42f8fd33c31 100644 --- a/examples/translator/config/config.textproto +++ b/examples/translator/config/config.textproto @@ -8,8 +8,6 @@ node_configs { name: "grpc-server" grpc_server_config { address: "[::]:8080" - grpc_tls_private_key: "" - grpc_tls_certificate: "" } } node_configs { diff --git a/oak/proto/application.proto b/oak/proto/application.proto index dd418a98522..0d1e2d2e4a9 100644 --- a/oak/proto/application.proto +++ b/oak/proto/application.proto @@ -81,10 +81,6 @@ message GrpcServerConfiguration { // The endpoint address for the gRPC server to listen on. // `address` is represented as an "ip_address:tcp_port" string. string address = 1; - // Loaded private RSA key file used by a gRPC server pseudo-Node. - string grpc_tls_private_key = 2; - // Loaded PEM encoded X.509 TLS certificate file used by a gRPC server pseudo-Node. - string grpc_tls_certificate = 3; } // GrpcClientConfiguration describes the configuration of a gRPC client @@ -94,12 +90,9 @@ message GrpcClientConfiguration { // The URI component of a gRPC server endpoint. Must contain the "Host" element. // https://docs.rs/tonic/0.2.1/tonic/transport/struct.Uri.html string uri = 1; - // Loaded PEM encoded X.509 TLS root certificate file used to authenticate an external gRPC - // service. - string root_tls_certificate = 2; // The endpoint address of the external gRPC service. // `address` is represented as an "ip_address:tcp_port" string. - string address = 3; + string address = 2; } // RoughtimeClientConfiguration describes the configuration of a Roughtime diff --git a/oak/server/rust/oak_glue/src/lib.rs b/oak/server/rust/oak_glue/src/lib.rs index 1e83e03e6ce..8fab9645665 100644 --- a/oak/server/rust/oak_glue/src/lib.rs +++ b/oak/server/rust/oak_glue/src/lib.rs @@ -19,7 +19,8 @@ use lazy_static::lazy_static; use log::{debug, error, info, warn}; use oak_abi::OakStatus; use oak_runtime::{ - proto::oak::application::ApplicationConfiguration, runtime::RuntimeProxy, NodeId, + proto::oak::application::ApplicationConfiguration, runtime::RuntimeProxy, GrpcConfiguration, + NodeId, }; use prost::Message; use std::{convert::TryInto, io::Cursor, sync::RwLock}; @@ -115,14 +116,17 @@ pub unsafe extern "C" fn glue_start( // Configure the Rust Runtime, and run the gRPC server pseudo-Node as the implicit // initial Node. - let (grpc_proxy, grpc_handle) = - match oak_runtime::configure_and_run(app_config, runtime_config) { - Ok(p) => p, - Err(status) => { - error!("Failed to start runtime: {:?}", status); - return oak_abi::INVALID_HANDLE; - } - }; + let (grpc_proxy, grpc_handle) = match oak_runtime::configure_and_run( + app_config, + runtime_config, + GrpcConfiguration::default(), + ) { + Ok(p) => p, + Err(status) => { + error!("Failed to start runtime: {:?}", status); + return oak_abi::INVALID_HANDLE; + } + }; *node_id = grpc_proxy.node_id.0; info!( "runtime started, grpc_node_id={}, grpc_handle={}", diff --git a/oak/server/rust/oak_loader/BUILD b/oak/server/rust/oak_loader/BUILD index bec8ac29c2b..8f7a6a5e82e 100644 --- a/oak/server/rust/oak_loader/BUILD +++ b/oak/server/rust/oak_loader/BUILD @@ -31,9 +31,11 @@ rust_binary( "//cargo:anyhow", "//cargo:log", "//cargo:prost", + "//cargo:rustls", "//cargo:signal_hook", "//cargo:simple_logger", "//cargo:structopt", + "//cargo:tonic", "//oak/server/rust/oak_runtime", ], ) diff --git a/oak/server/rust/oak_loader/Cargo.toml b/oak/server/rust/oak_loader/Cargo.toml index 55eb92e4324..9e0ba1b5e3d 100644 --- a/oak/server/rust/oak_loader/Cargo.toml +++ b/oak/server/rust/oak_loader/Cargo.toml @@ -17,9 +17,13 @@ anyhow = "*" log = "*" oak_runtime = "=0.1.0" prost = "*" +rustls = "*" signal-hook = "*" simple_logger = "*" structopt = "*" +# Using an old version that is supported by `cargo-raze`: +# https://github.com/google/cargo-raze/issues/41#issuecomment-592274128 +tonic = { version = "=0.1.1", features = ["tls"] } [dev-dependencies] maplit = "*" diff --git a/oak/server/rust/oak_loader/src/main.rs b/oak/server/rust/oak_loader/src/main.rs index b4fe4a79ada..35913c68066 100644 --- a/oak/server/rust/oak_loader/src/main.rs +++ b/oak/server/rust/oak_loader/src/main.rs @@ -27,7 +27,10 @@ use anyhow::anyhow; use core::str::FromStr; use log::{debug, info}; -use oak_runtime::{configure_and_run, proto::oak::application::ApplicationConfiguration}; +use oak_runtime::{ + configure_and_run, + proto::oak::application::{ApplicationConfiguration, ConfigMap}, +}; use prost::Message; use std::{ collections::HashMap, @@ -39,15 +42,11 @@ use std::{ }, }; use structopt::StructOpt; +use tonic::transport::{Certificate, Identity}; #[cfg(test)] mod tests; -use oak_runtime::proto::oak::application::{ - node_configuration::ConfigType::{GrpcClientConfig, GrpcServerConfig}, - ConfigMap, -}; - #[derive(StructOpt, Clone, Debug)] #[structopt(about = "Oak Loader")] pub struct Opt { @@ -133,6 +132,18 @@ pub fn parse_config_map(config_files: &[ConfigEntry]) -> anyhow::Result anyhow::Result { + use rustls::internal::pemfile::certs; + + let mut cursor = std::io::Cursor::new(certificate); + // `rustls` doesn't specify certificate parsing errors: + // https://docs.rs/rustls/0.17.0/rustls/internal/pemfile/fn.certs.html + certs(&mut cursor).map_err(|()| anyhow!("could not parse TLS certificate"))?; + + Ok(Certificate::from_pem(certificate)) +} + fn main() -> anyhow::Result<()> { if cfg!(feature = "oak_debug") { simple_logger::init_by_env(); @@ -150,45 +161,42 @@ fn main() -> anyhow::Result<()> { // Load application configuration. let app_config_data = read_file(&opt.application)?; - let mut app_config = ApplicationConfiguration::decode(app_config_data.as_ref())?; - - // Assign a TLS identity to all gRPC server and client nodes in the application configuration. - let grpc_tls_private_key = read_to_string(&opt.grpc_tls_private_key)?; - let grpc_tls_certificate = read_to_string(&opt.grpc_tls_certificate)?; - let root_tls_certificate = read_to_string(&opt.root_tls_certificate)?; - for node in &mut app_config.node_configs { - if let Some(GrpcServerConfig(ref mut grpc_server_config)) = node.config_type { - grpc_server_config.grpc_tls_private_key = grpc_tls_private_key.clone(); - grpc_server_config.grpc_tls_certificate = grpc_tls_certificate.clone(); - } else if let Some(GrpcClientConfig(ref mut grpc_client_config)) = node.config_type { - grpc_client_config.root_tls_certificate = root_tls_certificate.clone(); - } - } + let application_configuration = ApplicationConfiguration::decode(app_config_data.as_ref())?; // Create Runtime config. - #[cfg(feature = "oak_debug")] - let runtime_config = oak_runtime::RuntimeConfiguration { - metrics_port: if opt.no_metrics { - None - } else { + let runtime_configuration = oak_runtime::RuntimeConfiguration { + metrics_port: if cfg!(feature = "oak_debug") && !opt.no_metrics { Some(opt.metrics_port) - }, - introspect_port: if opt.no_introspect { - None } else { + None + }, + introspect_port: if cfg!(feature = "oak_debug") && !opt.no_introspect { Some(opt.introspect_port) + } else { + None }, }; - #[cfg(not(feature = "oak_debug"))] - let runtime_config = oak_runtime::RuntimeConfiguration { - metrics_port: None, - introspect_port: None, + + // Create the overall gRPC configuration. + let grpc_tls_private_key = read_to_string(&opt.grpc_tls_private_key)?; + let grpc_tls_certificate = read_to_string(&opt.grpc_tls_certificate)?; + let root_tls_certificate = read_to_string(&opt.root_tls_certificate)?; + let grpc_configuration = oak_runtime::GrpcConfiguration { + grpc_server_tls_identity: Some(Identity::from_pem( + grpc_tls_certificate, + grpc_tls_private_key, + )), + grpc_client_root_tls_certificate: Some(load_certificate(&root_tls_certificate)?), }; // Start the Runtime from the given config. - info!("starting Runtime, config {:?}", runtime_config); - let (runtime, initial_handle) = configure_and_run(app_config, runtime_config) - .map_err(|status| anyhow!("status {:?}", status))?; + info!("starting Runtime, config {:?}", runtime_configuration); + let (runtime, initial_handle) = configure_and_run( + application_configuration, + runtime_configuration, + grpc_configuration, + ) + .map_err(|status| anyhow!("could not start runtime, status: {:?}", status))?; info!( "initial node {:?} with write handle {:?}", runtime.node_id, initial_handle diff --git a/oak/server/rust/oak_runtime/src/config.rs b/oak/server/rust/oak_runtime/src/config.rs index e4c510175c0..ef2e01cdb45 100644 --- a/oak/server/rust/oak_runtime/src/config.rs +++ b/oak/server/rust/oak_runtime/src/config.rs @@ -16,7 +16,7 @@ use crate::{ node, - node::{check_uri, load_certificate, load_wasm}, + node::{check_uri, load_wasm}, proto::oak::application::{ node_configuration::ConfigType, ApplicationConfiguration, GrpcClientConfiguration, GrpcServerConfiguration, LogConfiguration, NodeConfiguration, RoughtimeClientConfiguration, @@ -28,7 +28,6 @@ use itertools::Itertools; use log::error; use oak_abi::OakStatus; use std::collections::HashMap; -use tonic::transport::Identity; /// Create an application configuration. /// @@ -89,43 +88,32 @@ pub fn from_protobuf( return Err(OakStatus::ErrInvalidArgs); } Some(ConfigType::LogConfig(_)) => node::Configuration::LogNode, - Some(ConfigType::GrpcServerConfig(GrpcServerConfiguration { - address, - grpc_tls_private_key, - grpc_tls_certificate, - })) => node::Configuration::GrpcServerNode { - address: address.parse().map_err(|error| { - error!("Incorrect gRPC server address: {:?}", error); - OakStatus::ErrInvalidArgs - })?, - tls_identity: Identity::from_pem(grpc_tls_certificate, grpc_tls_private_key), - }, - Some(ConfigType::GrpcClientConfig(GrpcClientConfiguration { - uri, - root_tls_certificate, - address, - })) => node::Configuration::GrpcClientNode { - uri: uri - .parse() - .map_err(|error| { - error!("Error parsing URI {}: {:?}", uri, error); + Some(ConfigType::GrpcServerConfig(GrpcServerConfiguration { address })) => { + node::Configuration::GrpcServerNode { + address: address.parse().map_err(|error| { + error!("Incorrect gRPC server address: {:?}", error); OakStatus::ErrInvalidArgs - }) - .and_then(|uri| match check_uri(&uri) { - Ok(_) => Ok(uri), - Err(error) => { - error!("Incorrect URI {}: {:?}", uri, error); - Err(OakStatus::ErrInvalidArgs) - } })?, - root_tls_certificate: load_certificate(root_tls_certificate).map_err( - |error| { - error!("Error loading root certificate: {:?}", error); - OakStatus::ErrInvalidArgs - }, - )?, - address: address.to_string(), - }, + } + } + Some(ConfigType::GrpcClientConfig(GrpcClientConfiguration { uri, address })) => { + node::Configuration::GrpcClientNode { + uri: uri + .parse() + .map_err(|error| { + error!("Error parsing URI {}: {:?}", uri, error); + OakStatus::ErrInvalidArgs + }) + .and_then(|uri| match check_uri(&uri) { + Ok(_) => Ok(uri), + Err(error) => { + error!("Incorrect URI {}: {:?}", uri, error); + Err(OakStatus::ErrInvalidArgs) + } + })?, + address: address.to_string(), + } + } Some(ConfigType::WasmConfig(WebAssemblyConfiguration { module_bytes, .. })) => { load_wasm(&module_bytes).map_err(|error| { error!("Error loading Wasm module: {}", error); @@ -151,11 +139,12 @@ pub fn from_protobuf( /// passing the write [`oak_abi::Handle`] into the runtime will enable messages to be read /// back out from the [`RuntimeProxy`]. pub fn configure_and_run( - app_config: ApplicationConfiguration, - runtime_config: crate::RuntimeConfiguration, + application_configuration: ApplicationConfiguration, + runtime_configuration: crate::RuntimeConfiguration, + grpc_configuration: crate::GrpcConfiguration, ) -> Result<(RuntimeProxy, oak_abi::Handle), OakStatus> { - let configuration = from_protobuf(app_config)?; - let proxy = RuntimeProxy::create_runtime(configuration); - let handle = proxy.start_runtime(runtime_config)?; + let configuration = from_protobuf(application_configuration)?; + let proxy = RuntimeProxy::create_runtime(configuration, grpc_configuration); + let handle = proxy.start_runtime(runtime_configuration)?; Ok((proxy, handle)) } diff --git a/oak/server/rust/oak_runtime/src/lib.rs b/oak/server/rust/oak_runtime/src/lib.rs index cb4c6070acf..bef2e9373f0 100644 --- a/oak/server/rust/oak_runtime/src/lib.rs +++ b/oak/server/rust/oak_runtime/src/lib.rs @@ -32,13 +32,14 @@ pub mod metrics; pub mod node; pub mod runtime; -pub use config::{application_configuration, configure_and_run}; +use tonic::transport::{Certificate, Identity}; +pub use config::{application_configuration, configure_and_run}; pub use message::NodeMessage; pub use runtime::{NodeId, RuntimeProxy}; /// Configuration options that govern the behaviour of the Runtime itself. -#[derive(Debug)] +#[derive(Default, Debug)] pub struct RuntimeConfiguration { /// Port to run a metrics server on, if provided. pub metrics_port: Option, @@ -46,11 +47,15 @@ pub struct RuntimeConfiguration { pub introspect_port: Option, } -impl Default for RuntimeConfiguration { - fn default() -> Self { - RuntimeConfiguration { - metrics_port: None, - introspect_port: None, - } - } +/// Configuration options related to gRPC pseudo-Nodes. +/// +/// `Debug` is intentionally not implemented in order to avoid accidentally logging secrets. +#[derive(Default)] +pub struct GrpcConfiguration { + /// TLS identity to use for all gRPC Server Nodes. + pub grpc_server_tls_identity: Option, + + /// Root TLS certificate to use for all gRPC Client Nodes. + // TODO(#999): Remove user-configurable root CA. + pub grpc_client_root_tls_certificate: Option, } diff --git a/oak/server/rust/oak_runtime/src/node/mod.rs b/oak/server/rust/oak_runtime/src/node/mod.rs index fab8b78f4a7..dc531fc4458 100644 --- a/oak/server/rust/oak_runtime/src/node/mod.rs +++ b/oak/server/rust/oak_runtime/src/node/mod.rs @@ -14,7 +14,7 @@ // limitations under the License. // -use crate::runtime::RuntimeProxy; +use crate::{runtime::RuntimeProxy, GrpcConfiguration}; use log::debug; use std::{ net::{AddrParseError, SocketAddr}, @@ -22,7 +22,7 @@ use std::{ sync::Arc, }; use tokio::sync::oneshot; -use tonic::transport::{Certificate, Identity, Uri}; +use tonic::transport::Uri; pub mod external; mod grpc; @@ -57,14 +57,12 @@ pub enum Configuration { /// a TLS identity that consists of a private RSA key and an X.509 TLS certificate. GrpcServerNode { address: SocketAddr, - tls_identity: Identity, }, /// The configuration for a gRPC server pseudo-Node that contains a URI and an X.509 root TLS /// certificate. GrpcClientNode { uri: Uri, - root_tls_certificate: Certificate, address: String, }, @@ -148,18 +146,6 @@ pub fn check_uri(uri: &Uri) -> Result<(), ConfigurationError> { .ok_or(ConfigurationError::NoHostElement) } -/// Check the correctness of a PEM encoded TLS certificate. -pub fn load_certificate(certitiface: &str) -> Result { - use rustls::internal::pemfile::certs; - - let mut cursor = std::io::Cursor::new(certitiface); - // `rustls` doesn't specify certificate parsing errors: - // https://docs.rs/rustls/0.17.0/rustls/internal/pemfile/fn.certs.html - certs(&mut cursor).map_err(|_| ConfigurationError::CertificateParsingError)?; - - Ok(Certificate::from_pem(certitiface)) -} - impl Configuration { /// Creates a new Node instance corresponding to the [`Configuration`]. /// @@ -169,6 +155,7 @@ impl Configuration { node_name: &str, // Used for pretty debugging config_name: &str, entrypoint: String, + grpc_configuration: &GrpcConfiguration, ) -> Option> { debug!( "create_node('{}': '{}'.'{}')", @@ -176,23 +163,28 @@ impl Configuration { ); match self { Configuration::LogNode => Some(Box::new(logger::LogNode::new(node_name))), - Configuration::GrpcServerNode { - address, - tls_identity, - } => Some(Box::new(grpc::server::GrpcServerNode::new( - node_name, - *address, - tls_identity.clone(), - ))), - Configuration::GrpcClientNode { - uri, - root_tls_certificate, - address: _, - } => Some(Box::new(grpc::client::GrpcClientNode::new( - node_name, - uri.clone(), - root_tls_certificate.clone(), - ))), + Configuration::GrpcServerNode { address } => { + Some(Box::new(grpc::server::GrpcServerNode::new( + node_name, + *address, + grpc_configuration + .grpc_server_tls_identity + .as_ref() + .expect("no gRPC server TLS identity provided") + .clone(), + ))) + } + Configuration::GrpcClientNode { uri, address: _ } => { + Some(Box::new(grpc::client::GrpcClientNode::new( + node_name, + uri.clone(), + grpc_configuration + .grpc_client_root_tls_certificate + .as_ref() + .expect("no gRPC client root TLS certificate provided") + .clone(), + ))) + } Configuration::WasmNode { module } => { match wasm::WasmNode::new(node_name, module.clone(), entrypoint) { Some(node) => Some(Box::new(node)), diff --git a/oak/server/rust/oak_runtime/src/node/wasm/tests.rs b/oak/server/rust/oak_runtime/src/node/wasm/tests.rs index 1157d9270fa..8c13a05e623 100644 --- a/oak/server/rust/oak_runtime/src/node/wasm/tests.rs +++ b/oak/server/rust/oak_runtime/src/node/wasm/tests.rs @@ -15,7 +15,7 @@ // use super::*; -use crate::RuntimeProxy; +use crate::{GrpcConfiguration, RuntimeProxy}; use std::collections::HashMap; use wat::{parse_file, parse_str}; @@ -33,7 +33,7 @@ fn start_node>(buffer: S, entrypoint: &str) -> Result<(), OakStat module: Arc::new(module), }, ); - let proxy = RuntimeProxy::create_runtime(configuration); + let proxy = RuntimeProxy::create_runtime(configuration, GrpcConfiguration::default()); let (_write_handle, read_handle) = proxy.channel_create(&Label::public_trusted())?; let result = proxy.node_create( diff --git a/oak/server/rust/oak_runtime/src/proto/oak.application.rs b/oak/server/rust/oak_runtime/src/proto/oak.application.rs index 5190981fabe..63a4453463f 100644 --- a/oak/server/rust/oak_runtime/src/proto/oak.application.rs +++ b/oak/server/rust/oak_runtime/src/proto/oak.application.rs @@ -82,12 +82,6 @@ pub struct GrpcServerConfiguration { /// `address` is represented as an "ip_address:tcp_port" string. #[prost(string, tag="1")] pub address: std::string::String, - /// Loaded private RSA key file used by a gRPC server pseudo-Node. - #[prost(string, tag="2")] - pub grpc_tls_private_key: std::string::String, - /// Loaded PEM encoded X.509 TLS certificate file used by a gRPC server pseudo-Node. - #[prost(string, tag="3")] - pub grpc_tls_certificate: std::string::String, } /// GrpcClientConfiguration describes the configuration of a gRPC client /// pseudo-Node (which is provided by the Oak Runtime), connected to a specific @@ -98,13 +92,9 @@ pub struct GrpcClientConfiguration { /// https://docs.rs/tonic/0.2.1/tonic/transport/struct.Uri.html #[prost(string, tag="1")] pub uri: std::string::String, - /// Loaded PEM encoded X.509 TLS root certificate file used to authenticate an external gRPC - /// service. - #[prost(string, tag="2")] - pub root_tls_certificate: std::string::String, /// The endpoint address of the external gRPC service. /// `address` is represented as an "ip_address:tcp_port" string. - #[prost(string, tag="3")] + #[prost(string, tag="2")] pub address: std::string::String, } /// RoughtimeClientConfiguration describes the configuration of a Roughtime diff --git a/oak/server/rust/oak_runtime/src/runtime/mod.rs b/oak/server/rust/oak_runtime/src/runtime/mod.rs index b4f48a850dc..0edffc82669 100644 --- a/oak/server/rust/oak_runtime/src/runtime/mod.rs +++ b/oak/server/rust/oak_runtime/src/runtime/mod.rs @@ -19,6 +19,7 @@ use crate::{ metrics::Metrics, node, runtime::channel::{with_reader_channel, with_writer_channel, Channel}, + GrpcConfiguration, }; use core::sync::atomic::{AtomicBool, AtomicU64, Ordering::SeqCst}; use itertools::Itertools; @@ -249,7 +250,9 @@ impl Drop for AuxServer { /// Runtime structure for configuring and running a set of Oak Nodes. pub struct Runtime { - configuration: Configuration, + application_configuration: Configuration, + grpc_configuration: GrpcConfiguration, + terminating: AtomicBool, next_channel_id: AtomicU64, @@ -343,9 +346,13 @@ impl Runtime { // Methods on `RuntimeProxy` for managing the core `Runtime` instance. impl RuntimeProxy { /// Creates a [`Runtime`] instance with a single initial Node configured, and no channels. - pub fn create_runtime(configuration: Configuration) -> RuntimeProxy { + pub fn create_runtime( + configuration: Configuration, + grpc_configuration: GrpcConfiguration, + ) -> RuntimeProxy { let runtime = Arc::new(Runtime { - configuration, + application_configuration: configuration, + grpc_configuration, terminating: AtomicBool::new(false), next_channel_id: AtomicU64::new(0), @@ -378,8 +385,8 @@ impl RuntimeProxy { &self, runtime_config: crate::RuntimeConfiguration, ) -> Result { - let module_name = self.runtime.configuration.entry_module.clone(); - let entrypoint = self.runtime.configuration.entrypoint.clone(); + let module_name = self.runtime.application_configuration.entry_module.clone(); + let entrypoint = self.runtime.application_configuration.entrypoint.clone(); self.metrics_data() .runtime_metrics .runtime_health_check @@ -1249,7 +1256,7 @@ impl Runtime { let reader = self.abi_to_read_half(node_id, initial_handle)?; let config = self - .configuration + .application_configuration .nodes .get(config_name) .ok_or(OakStatus::ErrInvalidArgs)?; @@ -1279,7 +1286,12 @@ impl Runtime { debug!("{:?}: create node instance {:?}", node_id, new_node_id); // This only creates a Node instance, but does not start it. let instance = config - .create_node(&new_node_name, config_name, entrypoint.to_owned()) + .create_node( + &new_node_name, + config_name, + entrypoint.to_owned(), + &self.grpc_configuration, + ) .ok_or(OakStatus::ErrInvalidArgs)?; debug!("{:?}: start node instance {:?}", node_id, new_node_id); diff --git a/oak/server/rust/oak_runtime/src/runtime/tests.rs b/oak/server/rust/oak_runtime/src/runtime/tests.rs index f9b6dfdcab6..1c4a1c3046f 100644 --- a/oak/server/rust/oak_runtime/src/runtime/tests.rs +++ b/oak/server/rust/oak_runtime/src/runtime/tests.rs @@ -41,7 +41,7 @@ fn run_node_body(node_label: &Label, node_privilege: &NodePrivilege, node_body: entrypoint: "test_function".to_string(), }; info!("Create runtime for test"); - let proxy = crate::RuntimeProxy::create_runtime(configuration); + let proxy = crate::RuntimeProxy::create_runtime(configuration, GrpcConfiguration::default()); struct TestNode { node_body: Box, diff --git a/oak/server/rust/oak_runtime/tests/integration_test.rs b/oak/server/rust/oak_runtime/tests/integration_test.rs index 0ab2e6b7297..c805f294757 100644 --- a/oak/server/rust/oak_runtime/tests/integration_test.rs +++ b/oak/server/rust/oak_runtime/tests/integration_test.rs @@ -17,13 +17,11 @@ const METRICS_PORT: u16 = 9876; mod common { - use oak_runtime::runtime::RuntimeProxy; - use hyper::{Client, Uri}; use log::info; use maplit::hashmap; use oak_abi::OakStatus; - use oak_runtime::config; + use oak_runtime::{config, runtime::RuntimeProxy, GrpcConfiguration}; use wat::parse_str; pub fn start_runtime() -> Result<(RuntimeProxy, oak_abi::Handle), OakStatus> { @@ -54,6 +52,7 @@ mod common { metrics_port: Some(crate::METRICS_PORT), introspect_port: None, }, + GrpcConfiguration::default(), ) } diff --git a/sdk/rust/oak_tests/src/lib.rs b/sdk/rust/oak_tests/src/lib.rs index 81737421e05..cec613760e3 100644 --- a/sdk/rust/oak_tests/src/lib.rs +++ b/sdk/rust/oak_tests/src/lib.rs @@ -17,7 +17,6 @@ //! Test utilities to help with unit testing of Oak SDK code. use log::{debug, info}; - use prost::Message; use std::{collections::HashMap, process::Command}; @@ -84,7 +83,11 @@ pub fn run_single_module( entrypoint_name, ); - oak_runtime::configure_and_run(configuration, oak_runtime::RuntimeConfiguration::default()) + oak_runtime::configure_and_run( + configuration, + oak_runtime::RuntimeConfiguration::default(), + oak_runtime::GrpcConfiguration::default(), + ) } // TODO(#543): move this to oak_runtime as it's not test-specific