CA certificate HTTP endpoint for gurtca
This commit is contained in:
98
dns/Cargo.lock
generated
98
dns/Cargo.lock
generated
@@ -1027,6 +1027,30 @@ dependencies = [
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "headers"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06683b93020a07e3dbcf5f8c0f6d40080d725bea7936fc01ad345c01b97dc270"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"bytes",
|
||||
"headers-core",
|
||||
"http 0.2.12",
|
||||
"httpdate",
|
||||
"mime",
|
||||
"sha1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "headers-core"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429"
|
||||
dependencies = [
|
||||
"http 0.2.12",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "heck"
|
||||
version = "0.4.1"
|
||||
@@ -1462,6 +1486,24 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "multer"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01acbdc23469fd8fe07ab135923371d5f5a422fbf9c522158677c8eb15bc51c2"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"encoding_rs",
|
||||
"futures-util",
|
||||
"http 0.2.12",
|
||||
"httparse",
|
||||
"log",
|
||||
"memchr",
|
||||
"mime",
|
||||
"spin 0.9.8",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "7.1.3"
|
||||
@@ -1658,6 +1700,26 @@ version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a"
|
||||
dependencies = [
|
||||
"pin-project-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-internal"
|
||||
version = "1.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-lite"
|
||||
version = "0.2.14"
|
||||
@@ -2098,6 +2160,12 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
@@ -3176,6 +3244,35 @@ dependencies = [
|
||||
"try-lock",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "warp"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4378d202ff965b011c64817db11d5829506d3404edeadb61f190d111da3f231c"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"headers",
|
||||
"http 0.2.12",
|
||||
"hyper",
|
||||
"log",
|
||||
"mime",
|
||||
"mime_guess",
|
||||
"multer",
|
||||
"percent-encoding",
|
||||
"pin-project",
|
||||
"scoped-tls",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"tokio",
|
||||
"tokio-tungstenite",
|
||||
"tokio-util",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
@@ -3330,6 +3427,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"toml",
|
||||
"uuid",
|
||||
"warp",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
@@ -30,3 +30,4 @@ sha2 = "0.10"
|
||||
base64 = "0.22"
|
||||
uuid = { version = "1.0", features = ["v4"] }
|
||||
openssl = "0.10"
|
||||
warp = "0.3"
|
||||
|
||||
@@ -9,8 +9,13 @@ use colored::Colorize;
|
||||
use macros_rs::fmt::{crashln, string};
|
||||
use std::{sync::Arc, collections::HashMap};
|
||||
use gurt::prelude::*;
|
||||
use warp::Filter;
|
||||
use gurt::{GurtStatusCode, Route};
|
||||
|
||||
#[derive(Debug)]
|
||||
struct CertificateError;
|
||||
impl warp::reject::Reject for CertificateError {}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct AppState {
|
||||
config: Config,
|
||||
@@ -245,8 +250,74 @@ pub async fn start(cli: crate::Cli) -> std::io::Result<()> {
|
||||
.route(Route::get("/ca/certificate/*"), AppHandler { app_state: app_state.clone(), rate_limit_state: None, handler_type: HandlerType::GetCertificate })
|
||||
.route(Route::get("/ca/root"), AppHandler { app_state: app_state.clone(), rate_limit_state: None, handler_type: HandlerType::GetCaCertificate });
|
||||
|
||||
let http_port = 8876;
|
||||
let ca_bootstrap_server = start_ca_bootstrap_server(app_state.clone(), http_port, config.server.address.clone());
|
||||
|
||||
log::info!("Starting CA bootstrap HTTP server on {}:{}", config.server.address, http_port);
|
||||
log::info!("GURT server listening on {}", config.get_address());
|
||||
server.listen(&config.get_address()).await.map_err(|e| {
|
||||
std::io::Error::new(std::io::ErrorKind::Other, format!("GURT server error: {}", e))
|
||||
})
|
||||
|
||||
let result = tokio::try_join!(
|
||||
ca_bootstrap_server,
|
||||
async {
|
||||
server.listen(&config.get_address()).await.map_err(|e| {
|
||||
std::io::Error::new(std::io::ErrorKind::Other, format!("GURT server error: {}", e))
|
||||
})
|
||||
}
|
||||
);
|
||||
|
||||
match result {
|
||||
Ok(_) => Ok(()),
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
|
||||
async fn start_ca_bootstrap_server(app_state: AppState, port: u16, address: String) -> std::result::Result<(), std::io::Error> {
|
||||
let ca_root = warp::path("ca")
|
||||
.and(warp::path("root"))
|
||||
.and(warp::path::end())
|
||||
.and_then({
|
||||
let app_state = app_state.clone();
|
||||
move || {
|
||||
let app_state = app_state.clone();
|
||||
async move {
|
||||
match get_ca_certificate_content(&app_state).await {
|
||||
Ok(cert_pem) => {
|
||||
Ok(warp::reply::with_header(
|
||||
cert_pem,
|
||||
"content-type",
|
||||
"application/x-pem-file"
|
||||
))
|
||||
}
|
||||
Err(e) => {
|
||||
log::error!("Failed to get CA certificate: {}", e);
|
||||
Err(warp::reject::custom(CertificateError))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
let routes = ca_root
|
||||
.with(warp::cors().allow_any_origin().allow_methods(vec!["GET"]));
|
||||
|
||||
let addr: std::net::SocketAddr = format!("{}:{}", address, port).parse()
|
||||
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidInput, e))?;
|
||||
|
||||
warp::serve(routes).run(addr).await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn get_ca_certificate_content(app_state: &AppState) -> std::result::Result<String, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let query = "SELECT ca_cert_pem FROM ca_certificates WHERE is_active = TRUE ORDER BY created_at DESC LIMIT 1";
|
||||
let row: std::result::Result<(String,), _> = sqlx::query_as(query)
|
||||
.fetch_one(&app_state.db)
|
||||
.await;
|
||||
|
||||
match row {
|
||||
Ok((ca_cert_pem,)) => Ok(ca_cert_pem),
|
||||
Err(e) => {
|
||||
log::error!("Failed to retrieve CA certificate from database: {}", e);
|
||||
Err(format!("No active CA certificate found in database: {}", e).into())
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user