Add tls serving as an option

This commit is contained in:
Jeremy Wall 2023-01-02 19:47:40 -06:00
parent 09058914b0
commit 907af7f23c
5 changed files with 113 additions and 14 deletions

62
Cargo.lock generated
View File

@ -63,6 +63,12 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "arc-swap"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
[[package]] [[package]]
name = "argon2" name = "argon2"
version = "0.4.1" version = "0.4.1"
@ -312,6 +318,26 @@ dependencies = [
"tower-service", "tower-service",
] ]
[[package]]
name = "axum-server"
version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8456dab8f11484979a86651da8e619b355ede5d61a160755155f6c344bd18c47"
dependencies = [
"arc-swap",
"bytes",
"futures-util",
"http",
"http-body",
"hyper",
"pin-project-lite",
"rustls",
"rustls-pemfile",
"tokio",
"tokio-rustls",
"tower-service",
]
[[package]] [[package]]
name = "base64" name = "base64"
version = "0.13.0" version = "0.13.0"
@ -1156,9 +1182,9 @@ checksum = "0bfe8eed0a9285ef776bb792479ea3834e8b94e13d615c2f66d03dd50a435a29"
[[package]] [[package]]
name = "httparse" name = "httparse"
version = "1.7.1" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]] [[package]]
name = "httpdate" name = "httpdate"
@ -1168,9 +1194,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "0.14.20" version = "0.14.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" checksum = "034711faac9d2166cb1baf1a2fb0b60b1f277f8492fd72176c17f3515e1abd3c"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
@ -1285,6 +1311,7 @@ dependencies = [
"async-trait", "async-trait",
"axum", "axum",
"axum-auth", "axum-auth",
"axum-server",
"chrono", "chrono",
"ciborium", "ciborium",
"clap", "clap",
@ -1994,9 +2021,9 @@ checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
[[package]] [[package]]
name = "socket2" name = "socket2"
version = "0.4.4" version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" checksum = "02e2d2db9033d13a1567121ddd7a095ee144db4e1ca1b1bda3419bc0da294ebd"
dependencies = [ dependencies = [
"libc", "libc",
"winapi", "winapi",
@ -2357,9 +2384,32 @@ dependencies = [
"once_cell", "once_cell",
"pin-project-lite", "pin-project-lite",
"socket2", "socket2",
"tokio-macros",
"winapi", "winapi",
] ]
[[package]]
name = "tokio-macros"
version = "1.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tokio-rustls"
version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
dependencies = [
"rustls",
"tokio",
"webpki",
]
[[package]] [[package]]
name = "tokio-util" name = "tokio-util"
version = "0.7.3" version = "0.7.3"

View File

@ -29,6 +29,10 @@ version = "0.4.1"
version = "0.8.0" version = "0.8.0"
features = ["serde"] features = ["serde"]
[dependencies.axum-server]
version = "0.4.4"
features = [ "tls-rustls" ]
[dependencies.axum-auth] [dependencies.axum-auth]
version = "0.3.0" version = "0.3.0"
features = ["auth-basic"] features = ["auth-basic"]

View File

@ -45,7 +45,10 @@ fn create_app<'a>() -> clap::App<'a> {
(@subcommand serve => (@subcommand serve =>
(about: "Serve the interface via the web") (about: "Serve the interface via the web")
(@arg recipe_dir: -d --dir +takes_value "Directory containing recipe files to use") (@arg recipe_dir: -d --dir +takes_value "Directory containing recipe files to use")
(@arg session_dir: --session_dir + takes_value "Session store directory to use") (@arg session_dir: --session_dir +takes_value "Session store directory to use")
(@arg tls: --tls "Use TLS to serve.")
(@arg cert_path: --cert +takes_value "Certificate path. Required if you specified --tls.")
(@arg key_path: --cert_key +takes_value "Certificate key path. Required if you specified --tls")
(@arg listen: --listen +takes_value "address and port to listen on 0.0.0.0:3030") (@arg listen: --listen +takes_value "address and port to listen on 0.0.0.0:3030")
) )
(@subcommand add_user => (@subcommand add_user =>
@ -136,7 +139,22 @@ fn main() {
}; };
info!(listen=%listen_socket, "Launching web interface..."); info!(listen=%listen_socket, "Launching web interface...");
async_std::task::block_on(async { async_std::task::block_on(async {
web::ui_main(recipe_dir_path, session_store_path, listen_socket).await if matches.contains_id("tls") {
web::ui_main_tls(
recipe_dir_path,
session_store_path,
listen_socket,
matches
.value_of("cert_path")
.expect("You must provide a cert path with --cert"),
matches
.value_of("key_path")
.expect("You must provide a key path with --cert_key"),
)
.await
} else {
web::ui_main(recipe_dir_path, session_store_path, listen_socket).await
}
}); });
} else if let Some(matches) = matches.subcommand_matches("add_user") { } else if let Some(matches) = matches.subcommand_matches("add_user") {
let recipe_dir_path = matches.value_of("recipe_dir").map(|dir| PathBuf::from(dir)); let recipe_dir_path = matches.value_of("recipe_dir").map(|dir| PathBuf::from(dir));

View File

@ -355,8 +355,8 @@ fn mk_v2_routes() -> Router {
) )
} }
#[instrument(fields(recipe_dir=?recipe_dir_path,listen=?listen_socket), skip_all)] #[instrument(fields(recipe_dir=?recipe_dir_path), skip_all)]
pub async fn ui_main(recipe_dir_path: PathBuf, store_path: PathBuf, listen_socket: SocketAddr) { pub async fn make_router(recipe_dir_path: PathBuf, store_path: PathBuf) -> Router {
let store = Arc::new(storage::file_store::AsyncFileStore::new( let store = Arc::new(storage::file_store::AsyncFileStore::new(
recipe_dir_path.clone(), recipe_dir_path.clone(),
)); ));
@ -369,7 +369,7 @@ pub async fn ui_main(recipe_dir_path: PathBuf, store_path: PathBuf, listen_socke
.run_migrations() .run_migrations()
.await .await
.expect("Failed to run database migrations"); .expect("Failed to run database migrations");
let router = Router::new() Router::new()
.route("/", get(|| async { Redirect::temporary("/ui/plan") })) .route("/", get(|| async { Redirect::temporary("/ui/plan") }))
.route("/favicon.ico", get(|| async { StaticFile("favicon.ico") })) .route("/favicon.ico", get(|| async { StaticFile("favicon.ico") }))
.route("/ui/*path", get(ui_static_assets)) .route("/ui/*path", get(ui_static_assets))
@ -390,12 +390,39 @@ pub async fn ui_main(recipe_dir_path: PathBuf, store_path: PathBuf, listen_socke
.layer(TraceLayer::new_for_http()) .layer(TraceLayer::new_for_http())
.layer(Extension(store)) .layer(Extension(store))
.layer(Extension(app_store)), .layer(Extension(app_store)),
); )
}
#[instrument(fields(recipe_dir=?recipe_dir_path,listen=?listen_socket), skip_all)]
pub async fn ui_main_tls(
recipe_dir_path: PathBuf,
store_path: PathBuf,
listen_socket: SocketAddr,
cert_path: &str,
key_path: &str,
) {
let router = make_router(recipe_dir_path, store_path).await;
info!( info!(
http = format!("http://{}", listen_socket), http = format!("http://{}", listen_socket),
"Starting server" "Starting server"
); );
axum::Server::bind(&listen_socket) let config = axum_server::tls_rustls::RustlsConfig::from_pem_file(cert_path, key_path)
.await
.expect("Failed to parse config from pem files");
axum_server::bind_rustls(listen_socket, config)
.serve(router.into_make_service())
.await
.expect("Failed to start tls service");
}
#[instrument(fields(recipe_dir=?recipe_dir_path,listen=?listen_socket), skip_all)]
pub async fn ui_main(recipe_dir_path: PathBuf, store_path: PathBuf, listen_socket: SocketAddr) {
let router = make_router(recipe_dir_path, store_path).await;
info!(
http = format!("http://{}", listen_socket),
"Starting server"
);
axum_server::bind(listen_socket)
.serve(router.into_make_service()) .serve(router.into_make_service())
.await .await
.expect("Failed to start service"); .expect("Failed to start service");

2
run.sh
View File

@ -14,5 +14,5 @@
EXAMPLES=${EXAMPLES:-../examples} EXAMPLES=${EXAMPLES:-../examples}
make clean wasm kitchen make clean wasm kitchen
echo Starting api server serving ${EXAMPLES} echo Starting api server serving ${EXAMPLES}
cargo run -- --verbose debug serve --dir ${EXAMPLES} cargo run -- --verbose debug serve --dir ${EXAMPLES} --tls --cert ~/tls-certs/localhost+2.pem --cert_key ~/tls-certs/localhost+2-key.pem
# This is ghetto but I'm doing it anyway # This is ghetto but I'm doing it anyway