Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rust Oak Loader #749

Merged
merged 7 commits into from
Apr 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ members = [
"experimental/split_grpc/proxy",
"experimental/split_grpc/server",
"oak/server/rust/oak_abi",
"oak/server/rust/oak_loader",
"oak/server/rust/oak_runtime",
"runner",
"sdk/rust/oak",
Expand All @@ -35,6 +36,7 @@ members = [
# Oak.
oak = { path = "sdk/rust/oak" }
oak_abi = { path = "oak/server/rust/oak_abi" }
oak_loader = { path = "oak/server/rust/oak_loader" }
oak_runtime = { path = "oak/server/rust/oak_runtime" }
oak_tests = { path = "sdk/rust/oak_tests" }
oak_utils = { path = "sdk/rust/oak_utils" }
Expand Down
13 changes: 13 additions & 0 deletions oak/server/rust/oak_loader/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "oak_loader"
version = "0.1.0"
authors = ["Ivan Petrov <[email protected]>"]
edition = "2018"
license = "Apache-2.0"

[dependencies]
env_logger = "*"
log = "*"
oak_runtime = "=0.1.0"
prost = "*"
structopt = "*"
71 changes: 71 additions & 0 deletions oak/server/rust/oak_loader/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// Copyright 2020 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! An utility binary to run Oak Runtime.
//!
//! To invoke, run the following command from the root of the repository:
//!
//! ```
//! cargo run --package=oak_loader -- --application=<APP_CONFIG_PATH>
//! ```

use log::info;
use oak_runtime::{configure_and_run, proto::ApplicationConfiguration};
use prost::Message;
use std::{fs::File, io::Read, thread::park};
use structopt::StructOpt;

#[derive(StructOpt, Clone)]
#[structopt(about = "Oak Loader")]
pub struct Opt {
#[structopt(long, help = "Application configuration file")]
application: String,
// TODO(#806): Make arguments non-optional once TLS support is enabled.
#[structopt(long, help = "Path to the PEM-encoded CA root certificate")]
ca_cert: Option<String>,
#[structopt(long, help = "Path to the private key")]
private_key: Option<String>,
#[structopt(long, help = "Path to the PEM-encoded certificate chain")]
cert_chain: Option<String>,
}

fn read_file(filename: &str) -> Result<Vec<u8>, Box<dyn std::error::Error>> {
let mut file = File::open(filename)
.map_err(|error| format!("Failed to open file <{}>: {:?}", filename, error))?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)
.map_err(|error| format!("Failed to read file <{}>: {:?}", filename, error))?;
Ok(buffer)
}

fn main() -> Result<(), Box<dyn std::error::Error>> {
env_logger::init();
info!("Loading Oak Runtime");

let opt = Opt::from_args();
let app_config = {
let buffer = read_file(&opt.application)?;
ApplicationConfiguration::decode(&buffer[..])
.map_err(|error| format!("Failed to decode application configuration: {:?}", error))?
};

// Spawns a new thread corresponding to an initial Wasm Oak node.
configure_and_run(app_config).map_err(|error| format!("Runtime error: {:?}", error))?;
// Park current thread.
park();

Ok(())
}
23 changes: 15 additions & 8 deletions scripts/build_server
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Build the specified version of the Oak Runtime server.

-s Server type:
- base: base version of the server (default)
- rust: Rust version of the server
- arm: server for ARM architecture
- asan: server with address sanitizer
- tsan: server with thread santizer
Expand All @@ -23,6 +24,8 @@ Build the specified version of the Oak Runtime server.
case "${OPTARG}" in
base)
config='clang';;
rust)
config='rust';;
arm)
config='armv8';;
asan)
Expand All @@ -39,12 +42,16 @@ Build the specified version of the Oak Runtime server.
esac
done

bazel_build_flags+=(
"--config=${config}"
)
if [[ "${config}" == "rust" ]]; then
cargo build --package=oak_loader
else
bazel_build_flags+=(
"--config=${config}"
)

# Use a different output_base so that we don't lose incremental state.
# See https://docs.bazel.build/versions/master/command-line-reference.html#flag--output_base.
bazel --output_base="${CACHE_DIR}/$config" build "${bazel_build_flags[@]}" \
//oak/server/loader:oak_runner \
//oak/server/storage:storage_server
# Use a different output_base so that we don't lose incremental state.
# See https://docs.bazel.build/versions/master/command-line-reference.html#flag--output_base.
bazel --output_base="${CACHE_DIR}/$config" build "${bazel_build_flags[@]}" \
//oak/server/loader:oak_runner \
//oak/server/storage:storage_server
fi
4 changes: 4 additions & 0 deletions scripts/common
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ set -o errexit
set -o nounset
set -o xtrace

# Set the default Rust log level.
# https://docs.rs/env_logger
export RUST_LOG='info'

# See https://pantheon.corp.google.com/gcr/images/oak-ci/GLOBAL/oak
readonly DOCKER_IMAGE_NAME='gcr.io/oak-ci/oak'
readonly SERVER_DOCKER_IMAGE_NAME='gcr.io/oak-ci/oak-server'
Expand Down
13 changes: 9 additions & 4 deletions scripts/run_example
Original file line number Diff line number Diff line change
Expand Up @@ -7,32 +7,35 @@ source "${SCRIPTS_DIR}/common"
language="rust"
server="base"
buildargs=""
while getopts "s:l:de:h" opt; do
serverargs=""
while getopts "s:l:de:vh" opt; do
case "${opt}" in
h)
echo -e "Usage: ${0} [-h] [-s base|asan|tsan|none] [-l rust|cpp] [-d] -e EXAMPLE [-- CLIENT_ARGS]
echo -e "Usage: ${0} [-h] [-s base|asan|tsan|none] [-l rust|cpp] [-d] -e EXAMPLE [-- CLIENT_ARGS] [-v]

Build and run the given example Oak Application and client.

Options:
-e Example application name (required)
-s Server type used to run examples:
- base: base version of the server (default)
- rust: Rust version of the server
- asan: server with address sanitizer
- tsan: server with thread sanitizer
- none: run an application client without a server
-d Build C++ code for example using debug mode
-l Example application variant:
- rust (used by default)
- cpp
-v Enable verbose/debug output for the server
-h Print Help (this message) and exit
Options after -- will be passed to the example client program."
exit 0;;
l)
language="${OPTARG}";;
s)
case "${OPTARG}" in
base|asan|tsan|none)
base|rust|asan|tsan|none)
server="${OPTARG}";;
*)
echo "Invalid server type: ${OPTARG}"
Expand All @@ -42,6 +45,8 @@ Options after -- will be passed to the example client program."
buildargs='-d';;
e)
readonly EXAMPLE="${OPTARG}";;
v)
serverargs='-v';;
*)
echo "Invalid argument: ${OPTARG}"
exit 1;;
Expand All @@ -68,7 +73,7 @@ if [[ "${server}" != "none" ]]; then
# The server is being built before running, so the build process will not happen in the
# background.
"${SCRIPTS_DIR}/build_server" -s "${server}"
"${SCRIPTS_DIR}/run_server" -s "${server}" -l "${language}" -e "${EXAMPLE}" &
"${SCRIPTS_DIR}/run_server" ${serverargs} -s "${server}" -l "${language}" -e "${EXAMPLE}" &
readonly SERVER_PID=$!

function stop_server {
Expand Down
30 changes: 21 additions & 9 deletions scripts/run_server
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@ source "${SCRIPTS_DIR}/common"

language="rust"
server="base"
while getopts "s:a:l:e:h" opt; do
while getopts "s:a:l:e:vh" opt; do
case "${opt}" in
h)
echo -e "Usage: ${0} [-s base|arm|asan|tsan] [-l rust|cpp] (-a APPLICATION | -e EXAMPLE)
echo -e "Usage: ${0} [-s base|arm|asan|tsan] [-l rust|cpp] (-a APPLICATION | -e EXAMPLE) [-v]

Run a particular Oak Application in the Oak Runtime.
Either the -a APPLICATION or the -e EXAMPLE option is required.
Expand All @@ -18,19 +18,21 @@ Either the -a APPLICATION or the -e EXAMPLE option is required.
-e Example application name
-s Server type:
- base: base version of the server (default)
- rust: Rust version of the server
- arm: server for ARM architecture
- asan: server with address sanitizer
- tsan: server with thread santizer
-l Example application variant (if -e specified):
- rust (used by default)
- cpp
-v Enable verbose/debug output
-h Print Help (this message) and exit"
exit 0;;
l)
language="${OPTARG}";;
s)
case "${OPTARG}" in
base|arm|asan|tsan)
base|rust|arm|asan|tsan)
server="${OPTARG}";;
*)
echo "Invalid server type: ${OPTARG}"
Expand All @@ -40,6 +42,8 @@ Either the -a APPLICATION or the -e EXAMPLE option is required.
readonly APPLICATION="${OPTARG}";;
e)
readonly EXAMPLE="${OPTARG}";;
v)
RUST_LOG='debug';;
*)
echo "Invalid argument: ${OPTARG}"
exit 1;;
Expand Down Expand Up @@ -73,9 +77,17 @@ fi

# Launching the server requires a `--application=<dir>/config.bin` flag.
# `exec` is necessary for the `run_example` script to be able to get a PID of a background server.
# We use a different symlink prefix for clang-based artifacts.
exec ./bazel-clang-bin/oak/server/loader/oak_runner \
--application="${APPLICATION}" \
--ca_cert="${SCRIPTS_DIR}/../examples/certs/local/ca.pem" \
--cert_chain="${SCRIPTS_DIR}/../examples/certs/local/local.pem" \
--private_key="${SCRIPTS_DIR}/../examples/certs/local/local.key"
if [[ "${server}" == "rust" ]]; then
exec cargo run --package=oak_loader -- \
--application="${APPLICATION}" \
--ca-cert="${SCRIPTS_DIR}/../examples/certs/local/ca.pem" \
--cert-chain="${SCRIPTS_DIR}/../examples/certs/local/local.pem" \
--private-key="${SCRIPTS_DIR}/../examples/certs/local/local.key"
else
# We use a different symlink prefix for clang-based artifacts.
exec ./bazel-clang-bin/oak/server/loader/oak_runner \
--application="${APPLICATION}" \
--ca_cert="${SCRIPTS_DIR}/../examples/certs/local/ca.pem" \
--cert_chain="${SCRIPTS_DIR}/../examples/certs/local/local.pem" \
--private_key="${SCRIPTS_DIR}/../examples/certs/local/local.key"
fi