Skip to content
Draft
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
21 changes: 17 additions & 4 deletions admin-tool/src/aio/configure.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ pub(super) struct Configuration {
#[clap(long, default_value_t = 8080)]
pub listen_port_manufacturing_server: u16,
#[clap(long, default_value_t = 8081)]
pub listen_port_owner_onboarding_server: u16,
pub listen_port_http_owner_onboarding_server: u16,
#[clap(long, default_value_t = 8085)]
pub listen_port_https_owner_onboarding_server: u16,
#[clap(long, default_value_t = 8082)]
pub listen_port_rendezvous_server: u16,
#[clap(long, default_value_t = 8083)]
Expand Down Expand Up @@ -78,7 +80,8 @@ impl Default for Configuration {

listen_ip_address: String::from("0.0.0.0"),
listen_port_manufacturing_server: 8080,
listen_port_owner_onboarding_server: 8081,
listen_port_http_owner_onboarding_server: 8081,
listen_port_https_owner_onboarding_server: 8085,
listen_port_rendezvous_server: 8082,
listen_port_serviceinfo_api_server: 8083,

Expand Down Expand Up @@ -155,7 +158,7 @@ impl Configuration {
Ok(vec![fdo_data_formats::types::RemoteConnection::new(
fdo_data_formats::types::RemoteTransport::Http,
owner_addresses,
self.listen_port_owner_onboarding_server,
self.listen_port_http_owner_onboarding_server,
)])
}

Expand Down Expand Up @@ -309,7 +312,17 @@ fn generate_configs(aio_dir: &Path, config_args: &Configuration) -> Result<(), E
path: aio_dir.join("stores").join("owner_onboarding_sessions"),
},

bind: get_bind(config_args.listen_port_owner_onboarding_server)?,
owner_server_https_cert: AbsolutePathBuf::new(
aio_dir.join("keys").join("owner_server_https_cert.crt"),
)
.unwrap(),
owner_server_https_key: AbsolutePathBuf::new(
aio_dir.join("keys").join("owner_server_https_key.key"),
)
.unwrap(),

bind_http: get_bind(config_args.listen_port_http_owner_onboarding_server)?,
bind_https: get_bind(config_args.listen_port_https_owner_onboarding_server)?,

ownership_voucher_store_driver: StoreConfig::Directory {
path: aio_dir.join("stores").join("owner_vouchers"),
Expand Down
2 changes: 1 addition & 1 deletion admin-tool/src/aio/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,7 @@ impl ChildBinary {
fn port(&self, config: &Configuration) -> u16 {
match self {
ChildBinary::ManufacturingServer => config.listen_port_manufacturing_server,
ChildBinary::OwnerOnboardingServer => config.listen_port_owner_onboarding_server,
ChildBinary::OwnerOnboardingServer => config.listen_port_http_owner_onboarding_server,
ChildBinary::RendezvousServer => config.listen_port_rendezvous_server,
ChildBinary::ServiceInfoApiServer => config.listen_port_serviceinfo_api_server,
_ => unreachable!(),
Expand Down
2 changes: 1 addition & 1 deletion http-wrapper/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ aws-nitro-enclaves-cose = "0.4.0"

# Server-side
uuid = { version = "1.3", features = ["v4"], optional = true }
warp = { version = "0.3", optional = true }
warp = { version = "0.3", optional = true, default-features = false }
warp-sessions = { version = "1.0", optional = true }
time = "0.3"

Expand Down
79 changes: 79 additions & 0 deletions integration-tests/tests/ov_management.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
mod common;
use anyhow::{bail, Context, Result};
use common::{Binary, TestContext};

#[tokio::test]
async fn test_ov_management() -> Result<()> {
let mut ctx = TestContext::new().context("Error building test context")?;
// start server
let owner_onboarding_server = ctx
.start_test_server(
Binary::OwnerOnboardingServer,
|cfg| {
Ok(cfg.prepare_config_file(None, |cfg| {
cfg.insert("serviceinfo_api_server_port", &8083);
Ok(())
})?)
},
|_| Ok(()),
)
.context("Error creating owner server")?;
ctx.wait_until_servers_ready()
.await
.context("Error waiting for servers to start")?;

//sending request
let client = reqwest::Client::new();

let add_ov = client
.post(format!(
"https://localhost:{}/management/v1/ownership_voucher", //DevSkim: ignore DS137138

Check notice

Code scanning / devskim

Accessing localhost could indicate debug code, or could hinder scaling.

Do not leave debug code in production
owner_onboarding_server.server_port().unwrap()
))
.header("Authorization", "Bearer TestAdminToken")
.header("X-Number-Of-Vouchers", "1")
.header("content-type", "application/x-pem-file")
.body("THIS IS A INVALID BODY")
.send()
.await?;
let mut failed = Vec::new();
if add_ov.status() != 400 {
failed.push(TestCase {
action: "Add OV",
error: format!("expected 400 got {}", add_ov.status()),
})
}

let ov_list: [&str; 1] = ["89cb17fd-95e7-4de8-a36a-686926a7f88f"];
let delete_ov = client
.post(format!(
"http://localhost:{}/management/v1/ownership_voucher/delete",

Check notice

Code scanning / devskim

Accessing localhost could indicate debug code, or could hinder scaling.

Do not leave debug code in production
owner_onboarding_server.server_port().unwrap()
))
.json(&ov_list)
.send()
.await?;
if delete_ov.status() != 400 {
failed.push(TestCase {
action: "Delete OV",
error: format!("expected 400 got {}", delete_ov.status()),
})
}

if failed.is_empty() {
Ok(())
} else {
for failed_case in failed {
eprintln!("Failed test: {:?}", failed_case);
}
bail!("Some tests failed");
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you also need to test when a proper OV is sent in PEM format, when a proper OV is sent in cbor format, when multiple OVs are sent in both formats, when the formats are mixed up and when the actual OV count does not match the sent OV count.


#[derive(Debug)]
struct TestCase {
#[allow(dead_code)]
action: &'static str,
#[allow(dead_code)]
error: String,
}
5 changes: 4 additions & 1 deletion owner-onboarding-server/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@ tokio = { version = "1", features = ["full"] }
thiserror= "1"
serde = "1"
openssl = "0.10.55"
warp = "0.3"
warp = { version = "0.3", default-features = false, features = ["tls"]}
hyper = { version = "0.14", features = ["tcp"] }
tls-listener = { version = "0.7.0", features = ["openssl", "hyper-h1"]}
serde_bytes = "0.11"
serde_cbor = "0.11"
serde_json = "1.0.79"
log = "0.4"
serde_yaml = "0.9"
time = "0.3"
Expand Down
102 changes: 75 additions & 27 deletions owner-onboarding-server/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,18 @@ use fdo_util::servers::{
configuration::{owner_onboarding_server::OwnerOnboardingServerSettings, AbsolutePathBuf},
settings_for, OwnershipVoucherStoreMetadataKey,
};
use hyper::server::conn::AddrIncoming;
use std::convert::Infallible;
use tls_listener::TlsListener;

pub mod tls_config;
use tls_config::tls_acceptor;

mod handlers;
mod ov_management;
use crate::ov_management::ov_filter;

pub(crate) struct OwnerServiceUD {
pub struct OwnerServiceUD {
// Trusted keys
#[allow(dead_code)]
trusted_device_keys: X5Bag,
Expand All @@ -50,6 +58,8 @@ pub(crate) struct OwnerServiceUD {
>,
>,
session_store: Arc<fdo_http_wrapper::server::SessionStore>,
owner_server_https_cert: AbsolutePathBuf,
owner_server_https_key: AbsolutePathBuf,

// Our keys
owner_key: PKey<Private>,
Expand Down Expand Up @@ -277,7 +287,8 @@ async fn main() -> Result<()> {
.context("Error parsing configuration")?;

// Bind information
let bind_addr = settings.bind.clone();
let bind_http_addr = settings.bind_http.clone();
let bind_https_addr = settings.bind_https.clone();

// Trusted keys
let trusted_device_keys = {
Expand Down Expand Up @@ -343,6 +354,8 @@ async fn main() -> Result<()> {
// Stores
ownership_voucher_store,
session_store: session_store.clone(),
owner_server_https_cert: settings.owner_server_https_cert,
owner_server_https_key: settings.owner_server_https_key,

// Trusted keys
trusted_device_keys,
Expand Down Expand Up @@ -415,40 +428,75 @@ async fn main() -> Result<()> {
let routes = warp::post()
.and(
hello
.or(handler_ping)
.or(handler_report_to_rendezvous)
.or(handler_ping.clone())
.or(handler_report_to_rendezvous.clone())
// TO2
.or(handler_to2_hello_device)
.or(handler_to2_get_ov_next_entry)
.or(handler_to2_prove_device)
.or(handler_to2_device_service_info_ready)
.or(handler_to2_device_service_info)
.or(handler_to2_done),
.or(handler_to2_hello_device.clone())
.or(handler_to2_get_ov_next_entry.clone())
.or(handler_to2_prove_device.clone())
.or(handler_to2_device_service_info_ready.clone())
.or(handler_to2_device_service_info.clone())
.or(handler_to2_done.clone())
.or(ov_filter(user_data.clone())),
)
.recover(fdo_http_wrapper::server::handle_rejection)
.with(warp::log("owner-onboarding-service"));
.with(warp::log(
"owner-onboarding-service to handle http and https",
));

log::info!("Listening on {}", bind_addr);
let server = warp::serve(routes);
let service = warp::service(routes.clone());

let maintenance_runner =
tokio::spawn(async move { perform_maintenance(user_data.clone()).await });
let make_svc = hyper::service::make_service_fn(move |_| {
let svc = service.clone();
async move { Ok::<_, Infallible>(svc) }
});

let server = server
.bind_with_graceful_shutdown(bind_addr, async {
let incoming = TlsListener::new(
tls_acceptor(user_data.clone()),
AddrIncoming::bind(&bind_https_addr.into())?,
);
let https_server = hyper::Server::builder(incoming).serve(make_svc);
let https_server = https_server.with_graceful_shutdown(async {
signal(SignalKind::terminate()).unwrap().recv().await;
log::info!("Terminating HTTPS server");
});
let https_server_handle = tokio::spawn(https_server);

let http_server = warp::serve(routes.clone());
let http_server = http_server
.bind_with_graceful_shutdown(bind_http_addr, async {
signal(SignalKind::terminate()).unwrap().recv().await;
log::info!("Terminating");
log::info!("Terminating HTTP server");
})
.1;
let server = tokio::spawn(server);

tokio::select!(
_ = server => {
log::info!("Server terminated");
},
_ = maintenance_runner => {
log::info!("Maintenance runner terminated");
Comment thread
rdotjain marked this conversation as resolved.
});
let http_server_handle = tokio::spawn(http_server);

let maintenance_runner_handle =
tokio::spawn(async move { perform_maintenance(user_data.clone()).await });

log::info!("starting both servers with http & https support");
// Join all the three handlers and wait
let (http_result, https_result, maintenance_result) = tokio::join!(
http_server_handle,
https_server_handle,
maintenance_runner_handle
);

// Check the results and handle accordingly since we have joined
match http_result {
Ok(_) => log::info!("HTTP server terminated successfully"),
Err(err) => log::error!("HTTP server terminated with an error: {:?}", err),
}

match https_result {
Ok(_) => log::info!("HTTPS server terminated successfully"),
Err(err) => log::error!("HTTPS server terminated with an error: {:?}", err),
}

match maintenance_result {
Ok(_) => log::info!("Maintenance runner terminated successfully"),
Err(err) => log::error!("Maintenance runner terminated with an error: {:?}", err),
}

Ok(())
}
Loading