Skip to content

Commit

Permalink
Introduce Oak Standalone Connector type
Browse files Browse the repository at this point in the history
Replace the hard-coded test behavior with a simple Connector
implementation in the test.

Change-Id: I0569c01c1cb8d9ea43a2d4060745907b64459e4c
  • Loading branch information
jblebrun committed Jun 27, 2024
1 parent 591ff84 commit 29e2b3b
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 6 deletions.
4 changes: 3 additions & 1 deletion oak_standalone/service/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ package(

rust_library(
name = "service",
srcs = ["src/service.rs"],
srcs = [
"src/service.rs",
],
crate_name = "oak_standalone_service",
deps = [
"//oak_client",
Expand Down
31 changes: 29 additions & 2 deletions oak_standalone/service/src/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ use oak_standalone_rust_bs_proto::oak::session::v1::{
use tokio::net::TcpListener;
use tokio_stream::wrappers::TcpListenerStream;

/// A simple request/response adapter between a client application and the Oak
/// Standalone facade.
///
/// Note: This is very similar to the [micro_rpc::Transport] trait. That type is
/// a great candidate for implementing an Adapter. But since other approaches
/// might be possible too, we keep the adapter type separate for now.
pub trait Adapter: Send + Sync {
/// Invoke the client request for the provided serialized request string.
///
/// The client should return a serialized response message that the Oak
/// Standalone facade will encrypt and return to the client.
fn invoke(&self, serialized_request: &[u8]) -> anyhow::Result<Vec<u8>>;
}

/// The structure that will implement the Oak Streaming Session crypto service
/// on behalf of a client's application. Right now, it just sets up the crypto
/// channel, but doesn't interact with any application yet.
Expand All @@ -56,11 +70,17 @@ struct OakStandaloneServiceImpl {
/// * We might add some sort of attestation/transparent release support.
/// * It's easier to transition later to a full Oak stack implementation.
endorsed_evidence: Arc<EndorsedEvidence>,

adapter: Arc<dyn Adapter>,
}

impl OakStandaloneServiceImpl {
/// Create a new instance of the server using the provided keypair.
fn new(private_encryption_key: EncryptionKey, public_key: Vec<u8>) -> Self {
fn new(
private_encryption_key: EncryptionKey,
public_key: Vec<u8>,
adapter: Arc<dyn Adapter>,
) -> Self {
Self {
private_encryption_key: Arc::new(private_encryption_key),

Expand All @@ -87,6 +107,7 @@ impl OakStandaloneServiceImpl {
r#type: Some(endorsements::Type::Standalone(OakStandaloneEndorsements {})),
}),
}),
adapter,
}
}
}
Expand All @@ -104,6 +125,7 @@ impl StreamingSession for OakStandaloneServiceImpl {

let private_key = self.private_encryption_key.clone();
let endorsed_evidence = self.endorsed_evidence.clone();
let adapter = self.adapter.clone();

let response_stream = async_stream::try_stream! {
while let Some(request) = request_stream.next().await {
Expand All @@ -124,7 +146,10 @@ impl StreamingSession for OakStandaloneServiceImpl {
let (server_encryptor, decrypted_request, _request_associated_data) =
ServerEncryptor::decrypt(&encrypted_request.encrypted_request.unwrap(), &*private_key)
.expect("server couldn't decrypt request");
let response: Vec<u8> = decrypted_request.into_iter().rev().collect();

let response = adapter.invoke(&decrypted_request)
.map_err(|err| tonic::Status::internal(format!("invoke failed: {err:?}")))?;

let encrypted_response = server_encryptor.encrypt(&response, b"")
.map_err(|err| tonic::Status::internal(format!("encrypt failed: {err:?}")))?;
response_wrapper::Response::InvokeResponse(InvokeResponse {
Expand All @@ -146,11 +171,13 @@ pub async fn create(
listener: TcpListener,
private_encryption_key: EncryptionKey,
public_key: Vec<u8>,
adapter: Arc<dyn Adapter>,
) -> Result<(), anyhow::Error> {
tonic::transport::Server::builder()
.add_service(StreamingSessionServer::new(OakStandaloneServiceImpl::new(
private_encryption_key,
public_key,
adapter,
)))
.serve_with_incoming(TcpListenerStream::new(listener))
.await
Expand Down
23 changes: 20 additions & 3 deletions oak_standalone/test/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@
// See the License for the specific language governing permissions and
// limitations under the License.

use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::{
net::{IpAddr, Ipv4Addr, SocketAddr},
sync::Arc,
};

use anyhow::{Context, Result};
use oak_client::{
Expand All @@ -23,18 +26,32 @@ use oak_client::{
use tokio::net::TcpListener;
use tonic::transport::Channel;

struct TestAdapter {}
impl oak_standalone_service::Adapter for TestAdapter {
fn invoke(&self, serialized_request: &[u8]) -> anyhow::Result<Vec<u8>> {
let reversed: Vec<u8> = serialized_request.iter().copied().rev().collect();
Ok(reversed)
}
}

async fn start_server() -> Result<(SocketAddr, tokio::task::JoinHandle<Result<()>>)> {
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0);
let listener = TcpListener::bind(addr).await?;
let addr = listener.local_addr()?;

let adapter = Arc::new(TestAdapter {});

let (private_encryption_key, public_key) =
oak_crypto::encryption_key::generate_encryption_key_pair();

println!("PK: {public_key:x?}");
Ok((
addr,
tokio::spawn(oak_standalone_service::create(listener, private_encryption_key, public_key)),
tokio::spawn(oak_standalone_service::create(
listener,
private_encryption_key,
public_key,
adapter,
)),
))
}

Expand Down

0 comments on commit 29e2b3b

Please sign in to comment.