diff --git a/Cargo.toml b/Cargo.toml index d7751d5..517de54 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,6 +26,13 @@ wasmtime-wasi = { version = "0.19.1", default-features = false } wasi-common = { version = "0.19.1", default-features = false } env_logger = "0.7" log = "0.4" +tokio = { version = "0.2", features = ["macros"] } +warp = { version = "0.2", features = ["tls"] } +serde = "1.0" +serde_json = "1.0" +serde_derive = "1.0" +openssl = { version = "0.10", features = ["vendored"] } + [build-dependencies] wat = "1.0" diff --git a/src/main.rs b/src/main.rs index 018cf5a..f4861d1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -18,23 +18,151 @@ //! ), //! ] //! ``` + #![deny(missing_docs)] #![deny(clippy::all)] +//#![feature(proc_macro_hygiene, decl_macro)] mod workload; +#[macro_use] +extern crate serde_derive; + +use openssl::asn1::Asn1Time; +use openssl::hash::MessageDigest; +use openssl::pkey::PKey; +use openssl::rsa::Rsa; + +use std::path::Path; +use warp::Filter; +#[derive(Serialize, Deserialize)] +struct Payload { + encoding: String, + contents: Vec, +} + use log::info; +/// Source of the key to use for TLS +//pub const KEY_SOURCE: &str = "file-system"; +pub const KEY_SOURCE: &str = "generate"; -fn main() { - let _ = env_logger::try_init_from_env(env_logger::Env::default()); +#[tokio::main] +async fn main() { + let args: Vec = std::env::args().skip(1).collect(); + let listen_port: u16 = args[0].parse().unwrap(); + let (server_key, server_cert) = get_credentials_bytes(); - let mut args = std::env::args().skip(1); - let path = args.next().unwrap(); - let vars = std::env::vars(); + // POST /payload + let workload = warp::post() + .and(warp::path("payload")) + .and(warp::body::json()) + .and_then(payload_launch); - let bytes = std::fs::read(&path).expect("Unable to open file"); + let routes = workload; + warp::serve(routes) + .tls() + .cert(&server_cert) + .key(&server_key) + //TODO - fix this so that we can bind to other IP addresses + .run(([127, 0, 0, 1], listen_port)) + .await; +} - let result = workload::run(&bytes, args, vars).expect("Failed to run workload"); +fn create_new_runtime(recvd_data: &[u8]) { + format!("About to attempt new runtime creation"); + let _ = env_logger::try_init_from_env(env_logger::Env::default()); + //TODO - get args these from main() if required + // let args = std::env::args().skip(1); + let dummy_arr: [&str; 1] = [""]; + let vars = std::env::vars(); + let result = workload::run(recvd_data, &dummy_arr, vars).expect("Failed to run workload"); + println!("Got result (println) {:#?}", result); info!("got result: {:#?}", result); } + +async fn payload_launch(payload: Payload) -> Result { + format!("Received a {} file", payload.encoding); + println!("Received a {} file", payload.encoding); + create_new_runtime(&payload.contents); + Ok(warp::reply::with_status( + "Payload received", + warp::http::StatusCode::OK, + )) +} + +fn get_credentials_bytes() -> (Vec, Vec) { + let (key, cert) = match KEY_SOURCE { + "file-system" => (get_key_bytes_fs(), get_cert_bytes_fs()), + "generate" => (generate_credentials()), + //no match! + _ => panic!("No match for credentials source"), + }; + (key, cert) +} + +//implementation for file system +fn get_cert_bytes_fs() -> Vec { + let in_path = Path::new("key-material/server.crt"); + + let in_contents = match std::fs::read(in_path) { + Ok(in_contents) => { + println!("Contents = of {} bytes", &in_contents.len()); + in_contents + } + Err(_) => { + println!("Failed to read from file"); + panic!("We have no data to use"); + } + }; + in_contents +} + +//implementation for file system +fn get_key_bytes_fs() -> Vec { + println!("Generating server key (PEM)"); + let in_path = Path::new("key-material/server.key"); + + let in_contents = match std::fs::read(in_path) { + Ok(in_contents) => { + println!("Contents = of {} bytes", &in_contents.len()); + in_contents + } + Err(_) => { + println!("Failed to read from file"); + panic!("We have no data to use"); + } + }; + in_contents +} + +//TODO - this is vital code, and needs to be carefully audited! +fn generate_credentials() -> (Vec, Vec) { + let key = Rsa::generate(2048).unwrap(); + let pkey = PKey::from_rsa(key.clone()).unwrap(); + + let mut x509_name = openssl::x509::X509NameBuilder::new().unwrap(); + x509_name.append_entry_by_text("C", "GB").unwrap(); + x509_name.append_entry_by_text("O", "enarx-test").unwrap(); + x509_name.append_entry_by_text("CN", "127.0.0.1").unwrap(); + let x509_name = x509_name.build(); + + let mut x509_builder = openssl::x509::X509::builder().unwrap(); + match x509_builder.set_not_before(&Asn1Time::days_from_now(0).unwrap()) { + Err(e) => panic!("Problem creating cert {}", e), + Ok(_) => {} + }; + match x509_builder.set_not_after(&Asn1Time::days_from_now(7).unwrap()) { + Err(e) => panic!("Problem creating cert {}", e), + Ok(_) => {} + }; + x509_builder.set_subject_name(&x509_name).unwrap(); + x509_builder.set_pubkey(&pkey).unwrap(); + x509_builder.sign(&pkey, MessageDigest::sha256()).unwrap(); + let certificate = x509_builder.build(); + + ( + key.private_key_to_pem().unwrap(), + certificate.to_pem().unwrap(), + ) +}