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-codec",
|
||||||
"actix-rt",
|
"actix-rt",
|
||||||
"actix-service",
|
"actix-service",
|
||||||
|
"actix-tls",
|
||||||
"actix-utils",
|
"actix-utils",
|
||||||
"ahash 0.8.7",
|
"ahash 0.8.7",
|
||||||
"base64",
|
"base64",
|
||||||
|
@ -160,6 +161,7 @@ dependencies = [
|
||||||
"actix-rt",
|
"actix-rt",
|
||||||
"actix-server",
|
"actix-server",
|
||||||
"actix-service",
|
"actix-service",
|
||||||
|
"actix-tls",
|
||||||
"actix-utils",
|
"actix-utils",
|
||||||
"ahash 0.8.7",
|
"ahash 0.8.7",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -1441,6 +1443,12 @@ version = "0.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6d02c0b00610773bb7fc61d85e13d86c7858cbdf00e1a120bfc41bc055dbaa0e"
|
checksum = "6d02c0b00610773bb7fc61d85e13d86c7858cbdf00e1a120bfc41bc055dbaa0e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "nanorand"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nom"
|
name = "nom"
|
||||||
version = "7.1.3"
|
version = "7.1.3"
|
||||||
|
@ -1806,6 +1814,7 @@ dependencies = [
|
||||||
"opentelemetry_sdk",
|
"opentelemetry_sdk",
|
||||||
"ructe",
|
"ructe",
|
||||||
"rustls",
|
"rustls",
|
||||||
|
"rustls-channel-resolver",
|
||||||
"rustls-pemfile",
|
"rustls-pemfile",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_qs",
|
"serde_qs",
|
||||||
|
@ -2192,6 +2201,16 @@ dependencies = [
|
||||||
"sct",
|
"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]]
|
[[package]]
|
||||||
name = "rustls-pemfile"
|
name = "rustls-pemfile"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
|
|
@ -17,7 +17,7 @@ default = []
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix-rt = "2.7.0"
|
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"
|
anyhow = "1.0"
|
||||||
awc = { version = "3.0.0", default-features = false, features = ["rustls-0_21"] }
|
awc = { version = "3.0.0", default-features = false, features = ["rustls-0_21"] }
|
||||||
clap = { version = "4.0.2", features = ["derive", "env"] }
|
clap = { version = "4.0.2", features = ["derive", "env"] }
|
||||||
|
@ -47,6 +47,7 @@ tracing-subscriber = { version = "0.3", features = [
|
||||||
] }
|
] }
|
||||||
url = "2.1"
|
url = "2.1"
|
||||||
webpki-roots = "0.26"
|
webpki-roots = "0.26"
|
||||||
|
rustls-channel-resolver = "0.1.0"
|
||||||
|
|
||||||
[dependencies.tracing-actix-web]
|
[dependencies.tracing-actix-web]
|
||||||
version = "0.7.9"
|
version = "0.7.9"
|
||||||
|
|
100
src/main.rs
100
src/main.rs
|
@ -10,6 +10,7 @@ use actix_web::{
|
||||||
middleware::NormalizePath,
|
middleware::NormalizePath,
|
||||||
web, App, HttpRequest, HttpResponse, HttpResponseBuilder, HttpServer, ResponseError,
|
web, App, HttpRequest, HttpResponse, HttpResponseBuilder, HttpServer, ResponseError,
|
||||||
};
|
};
|
||||||
|
use anyhow::Context;
|
||||||
use awc::{Client, Connector};
|
use awc::{Client, Connector};
|
||||||
use clap::Parser;
|
use clap::Parser;
|
||||||
use console_subscriber::ConsoleLayer;
|
use console_subscriber::ConsoleLayer;
|
||||||
|
@ -17,7 +18,10 @@ use once_cell::sync::Lazy;
|
||||||
use opentelemetry::KeyValue;
|
use opentelemetry::KeyValue;
|
||||||
use opentelemetry_otlp::WithExportConfig;
|
use opentelemetry_otlp::WithExportConfig;
|
||||||
use opentelemetry_sdk::{propagation::TraceContextPropagator, Resource};
|
use opentelemetry_sdk::{propagation::TraceContextPropagator, Resource};
|
||||||
use rustls::{Certificate, ClientConfig, OwnedTrustAnchor, RootCertStore};
|
use rustls::{
|
||||||
|
sign::CertifiedKey, Certificate, ClientConfig, OwnedTrustAnchor, PrivateKey, RootCertStore,
|
||||||
|
ServerConfig,
|
||||||
|
};
|
||||||
use std::{
|
use std::{
|
||||||
io::Cursor,
|
io::Cursor,
|
||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
|
@ -96,9 +100,23 @@ struct Config {
|
||||||
short,
|
short,
|
||||||
long,
|
long,
|
||||||
env = "PICTRS_PROXY_CERTIFICATE",
|
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>,
|
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 {
|
impl Config {
|
||||||
|
@ -880,7 +898,7 @@ fn init_tracing(
|
||||||
let subscriber = subscriber.with(console_layer);
|
let subscriber = subscriber.with(console_layer);
|
||||||
|
|
||||||
init_subscriber(subscriber, targets, opentelemetry_url, service_name)?;
|
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 {
|
} else {
|
||||||
init_subscriber(subscriber, targets, opentelemetry_url, service_name)?;
|
init_subscriber(subscriber, targets, opentelemetry_url, service_name)?;
|
||||||
}
|
}
|
||||||
|
@ -927,7 +945,7 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_rustls_config() -> anyhow::Result<ClientConfig> {
|
async fn rustls_client_config() -> anyhow::Result<ClientConfig> {
|
||||||
let mut cert_store = RootCertStore {
|
let mut cert_store = RootCertStore {
|
||||||
roots: webpki_roots::TLS_SERVER_ROOTS
|
roots: webpki_roots::TLS_SERVER_ROOTS
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
@ -955,6 +973,37 @@ async fn create_rustls_config() -> anyhow::Result<ClientConfig> {
|
||||||
.with_no_client_auth())
|
.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]
|
#[actix_rt::main]
|
||||||
async fn main() -> anyhow::Result<()> {
|
async fn main() -> anyhow::Result<()> {
|
||||||
dotenv::dotenv().ok();
|
dotenv::dotenv().ok();
|
||||||
|
@ -966,9 +1015,9 @@ async fn main() -> anyhow::Result<()> {
|
||||||
CONFIG.console_event_buffer_size,
|
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()
|
let client = Client::builder()
|
||||||
.wrap(Tracing)
|
.wrap(Tracing)
|
||||||
.add_default_header(("User-Agent", "pict-rs-frontend, v0.5.0"))
|
.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("/delete").route(web::get().to(delete)))
|
||||||
.service(web::resource("/404").route(web::get().to(not_found)))
|
.service(web::resource("/404").route(web::get().to(not_found)))
|
||||||
.default_service(web::get().to(go_home))
|
.default_service(web::get().to(go_home))
|
||||||
})
|
});
|
||||||
.bind(CONFIG.addr)?
|
|
||||||
|
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()
|
.run()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
handle.abort();
|
||||||
|
let _ = handle.await;
|
||||||
|
} else {
|
||||||
|
tracing::info!("Serving pict-rs-proxy on {}", CONFIG.addr);
|
||||||
|
|
||||||
|
server.bind(CONFIG.addr)?.run().await?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue