Compare commits
2 commits
232a1a04a1
...
26d4c3efe9
Author | SHA1 | Date | |
---|---|---|---|
asonix | 26d4c3efe9 | ||
asonix | e54432d020 |
19
Cargo.lock
generated
19
Cargo.lock
generated
|
@ -28,6 +28,7 @@ dependencies = [
|
|||
"actix-codec",
|
||||
"actix-rt",
|
||||
"actix-service",
|
||||
"actix-tls",
|
||||
"actix-utils",
|
||||
"ahash 0.8.7",
|
||||
"base64",
|
||||
|
@ -160,6 +161,7 @@ dependencies = [
|
|||
"actix-rt",
|
||||
"actix-server",
|
||||
"actix-service",
|
||||
"actix-tls",
|
||||
"actix-utils",
|
||||
"ahash 0.8.7",
|
||||
"bytes",
|
||||
|
@ -1441,6 +1443,12 @@ version = "0.0.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d02c0b00610773bb7fc61d85e13d86c7858cbdf00e1a120bfc41bc055dbaa0e"
|
||||
|
||||
[[package]]
|
||||
name = "nanorand"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
|
@ -1806,6 +1814,7 @@ dependencies = [
|
|||
"opentelemetry_sdk",
|
||||
"ructe",
|
||||
"rustls",
|
||||
"rustls-channel-resolver",
|
||||
"rustls-pemfile",
|
||||
"serde",
|
||||
"serde_qs",
|
||||
|
@ -2192,6 +2201,16 @@ dependencies = [
|
|||
"sct",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-channel-resolver"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de0a6bf546dc283b4c1413532d2bf53a64b3a006ee57f7ca0f4984f35841cacb"
|
||||
dependencies = [
|
||||
"nanorand",
|
||||
"rustls",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustls-pemfile"
|
||||
version = "2.0.0"
|
||||
|
|
|
@ -17,7 +17,7 @@ default = []
|
|||
|
||||
[dependencies]
|
||||
actix-rt = "2.7.0"
|
||||
actix-web = { version = "4.0.0", default-features = false }
|
||||
actix-web = { version = "4.0.0", default-features = false, features = ["rustls-0_21"] }
|
||||
anyhow = "1.0"
|
||||
awc = { version = "3.0.0", default-features = false, features = ["rustls-0_21"] }
|
||||
clap = { version = "4.0.2", features = ["derive", "env"] }
|
||||
|
@ -47,6 +47,7 @@ tracing-subscriber = { version = "0.3", features = [
|
|||
] }
|
||||
url = "2.1"
|
||||
webpki-roots = "0.26"
|
||||
rustls-channel-resolver = "0.1.0"
|
||||
|
||||
[dependencies.tracing-actix-web]
|
||||
version = "0.7.9"
|
||||
|
|
104
src/main.rs
104
src/main.rs
|
@ -10,6 +10,7 @@ use actix_web::{
|
|||
middleware::NormalizePath,
|
||||
web, App, HttpRequest, HttpResponse, HttpResponseBuilder, HttpServer, ResponseError,
|
||||
};
|
||||
use anyhow::Context;
|
||||
use awc::{Client, Connector};
|
||||
use clap::Parser;
|
||||
use console_subscriber::ConsoleLayer;
|
||||
|
@ -17,7 +18,10 @@ use once_cell::sync::Lazy;
|
|||
use opentelemetry::KeyValue;
|
||||
use opentelemetry_otlp::WithExportConfig;
|
||||
use opentelemetry_sdk::{propagation::TraceContextPropagator, Resource};
|
||||
use rustls::{Certificate, ClientConfig, OwnedTrustAnchor, RootCertStore};
|
||||
use rustls::{
|
||||
sign::CertifiedKey, Certificate, ClientConfig, OwnedTrustAnchor, PrivateKey, RootCertStore,
|
||||
ServerConfig,
|
||||
};
|
||||
use std::{
|
||||
io::Cursor,
|
||||
net::SocketAddr,
|
||||
|
@ -96,9 +100,23 @@ struct Config {
|
|||
short,
|
||||
long,
|
||||
env = "PICTRS_PROXY_CERTIFICATE",
|
||||
help = "Path to the certificate file to connec to pict-rs over TLS"
|
||||
help = "Path to the certificate file to connect to pict-rs over TLS"
|
||||
)]
|
||||
certificate: Option<PathBuf>,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
env = "PICTRS_PROXY_SERVER_CERTIFICATE",
|
||||
help = "Path to the certificate file to serve pict-rs-proxy over TLS"
|
||||
)]
|
||||
server_certificate: Option<PathBuf>,
|
||||
|
||||
#[arg(
|
||||
long,
|
||||
env = "PICTRS_PROXY_SERVER_PRIVATE_KEY",
|
||||
help = "Path to the private key file to serve pict-rs-proxy over TLS"
|
||||
)]
|
||||
server_private_key: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl Config {
|
||||
|
@ -880,7 +898,7 @@ fn init_tracing(
|
|||
let subscriber = subscriber.with(console_layer);
|
||||
|
||||
init_subscriber(subscriber, targets, opentelemetry_url, service_name)?;
|
||||
tracing::info!("Launched console on {console_addr}");
|
||||
tracing::info!("Serving tokio-console endpoint on {console_addr}");
|
||||
} else {
|
||||
init_subscriber(subscriber, targets, opentelemetry_url, service_name)?;
|
||||
}
|
||||
|
@ -927,7 +945,7 @@ where
|
|||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_rustls_config() -> anyhow::Result<ClientConfig> {
|
||||
async fn rustls_client_config() -> anyhow::Result<ClientConfig> {
|
||||
let mut cert_store = RootCertStore {
|
||||
roots: webpki_roots::TLS_SERVER_ROOTS
|
||||
.into_iter()
|
||||
|
@ -955,6 +973,37 @@ async fn create_rustls_config() -> anyhow::Result<ClientConfig> {
|
|||
.with_no_client_auth())
|
||||
}
|
||||
|
||||
async fn rustls_server_key() -> anyhow::Result<Option<CertifiedKey>> {
|
||||
let certificate_path = if let Some(c) = &CONFIG.server_certificate {
|
||||
c
|
||||
} else {
|
||||
tracing::info!("No server certificate");
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let private_key_path = if let Some(p) = &CONFIG.server_private_key {
|
||||
p
|
||||
} else {
|
||||
tracing::info!("No server private_key");
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
let cert_bytes = tokio::fs::read(certificate_path).await?;
|
||||
|
||||
let certs = rustls_pemfile::certs(&mut cert_bytes.as_slice())
|
||||
.map(|res| res.map(|c| Certificate(c.to_vec())))
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
let key_bytes = tokio::fs::read(private_key_path).await?;
|
||||
|
||||
let key =
|
||||
rustls_pemfile::private_key(&mut key_bytes.as_slice())?.context("No key in keyfile")?;
|
||||
|
||||
let signing_key = rustls::sign::any_supported_type(&PrivateKey(Vec::from(key.secret_der())))?;
|
||||
|
||||
Ok(Some(CertifiedKey::new(certs, signing_key)))
|
||||
}
|
||||
|
||||
#[actix_rt::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
dotenv::dotenv().ok();
|
||||
|
@ -966,9 +1015,9 @@ async fn main() -> anyhow::Result<()> {
|
|||
CONFIG.console_event_buffer_size,
|
||||
)?;
|
||||
|
||||
let client_config = create_rustls_config().await?;
|
||||
let client_config = rustls_client_config().await?;
|
||||
|
||||
HttpServer::new(move || {
|
||||
let server = HttpServer::new(move || {
|
||||
let client = Client::builder()
|
||||
.wrap(Tracing)
|
||||
.add_default_header(("User-Agent", "pict-rs-frontend, v0.5.0"))
|
||||
|
@ -999,10 +1048,45 @@ async fn main() -> anyhow::Result<()> {
|
|||
.service(web::resource("/delete").route(web::get().to(delete)))
|
||||
.service(web::resource("/404").route(web::get().to(not_found)))
|
||||
.default_service(web::get().to(go_home))
|
||||
})
|
||||
.bind(CONFIG.addr)?
|
||||
.run()
|
||||
.await?;
|
||||
});
|
||||
|
||||
if let Some(key) = rustls_server_key().await? {
|
||||
tracing::info!("Serving pict-rs-proxy over TLS on {}", CONFIG.addr);
|
||||
|
||||
let (tx, rx) = rustls_channel_resolver::channel::<32>(key);
|
||||
|
||||
let handle = actix_rt::spawn(async move {
|
||||
let mut interval = actix_rt::time::interval(Duration::from_secs(30));
|
||||
interval.tick().await;
|
||||
|
||||
loop {
|
||||
interval.tick().await;
|
||||
|
||||
match rustls_server_key().await {
|
||||
Ok(Some(key)) => tx.update(key),
|
||||
Ok(None) => tracing::warn!("Missing server certificates"),
|
||||
Err(e) => tracing::error!("Failed to read server certificates {e}"),
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let server_config = ServerConfig::builder()
|
||||
.with_safe_defaults()
|
||||
.with_no_client_auth()
|
||||
.with_cert_resolver(rx);
|
||||
|
||||
server
|
||||
.bind_rustls_021(CONFIG.addr, server_config)?
|
||||
.run()
|
||||
.await?;
|
||||
|
||||
handle.abort();
|
||||
let _ = handle.await;
|
||||
} else {
|
||||
tracing::info!("Serving pict-rs-proxy on {}", CONFIG.addr);
|
||||
|
||||
server.bind(CONFIG.addr)?.run().await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue