From ce80678a24d0922fd0e72a12d6f8f59d0aaa666a Mon Sep 17 00:00:00 2001 From: Matthew Hagemann Date: Tue, 26 Nov 2024 17:22:41 +0200 Subject: [PATCH 1/3] feat: tls termination handled by tonic server --- Cargo.lock | 7 +++++-- Cargo.toml | 2 +- src/config.rs | 4 ++++ src/grpc/mod.rs | 31 +++++++++++++++++++++++++++---- 4 files changed, 37 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d3fdcd4a..52dbd5cd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1778,9 +1778,9 @@ dependencies = [ [[package]] name = "rsa" -version = "0.9.6" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +checksum = "47c75d7c5c6b673e58bf54d8544a9f432e3a925b0e80f7cd3602ab5c50c55519" dependencies = [ "const-oid", "digest", @@ -1821,6 +1821,7 @@ version = "0.23.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c9cc1d47e243d655ace55ed38201c19ae02c148ae56412ab8750e8f0166ab7f" dependencies = [ + "log", "once_cell", "ring", "rustls-pki-types", @@ -2593,8 +2594,10 @@ dependencies = [ "percent-encoding", "pin-project", "prost 0.13.3", + "rustls-pemfile", "socket2", "tokio", + "tokio-rustls", "tokio-stream", "tower 0.4.13", "tower-layer", diff --git a/Cargo.toml b/Cargo.toml index c5223037..b079bedc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,7 +27,7 @@ strum = { version = "0.26.3", features = ["derive"] } thiserror = "1.0.64" time = "0.3" tokio = { version = "1.40.0", features = ["full"] } -tonic = "0.12.2" +tonic = { version = "0.12.2", features = ["tls"] } tonic-reflection = "0.12.2" tower = "0.5.1" tracing = "0.1.40" diff --git a/src/config.rs b/src/config.rs index 3b4dfb0a..cd2b41c4 100644 --- a/src/config.rs +++ b/src/config.rs @@ -16,6 +16,10 @@ pub struct Config { pub jwt_secret: SecretString, /// The base URI for snapcraft.io pub snapcraft_io_uri: String, + /// The path to the tls certificate + pub tls_cert_path: Option, + /// The path to the tls key + pub tls_key_path: Option, } impl Config { diff --git a/src/grpc/mod.rs b/src/grpc/mod.rs index 29b2ef66..bc39c014 100644 --- a/src/grpc/mod.rs +++ b/src/grpc/mod.rs @@ -1,6 +1,9 @@ -use crate::{db, jwt::JwtVerifier, middleware::AuthLayer, Context}; -use std::net::SocketAddr; -use tonic::{transport::Server, Status}; +use crate::{config, db, jwt::JwtVerifier, middleware::AuthLayer, Context}; +use std::{fs::read_to_string, net::SocketAddr}; +use tonic::{ + transport::{Identity, Server, ServerTlsConfig}, + Status, +}; mod app; mod charts; @@ -8,6 +11,7 @@ mod user; use app::RatingService; use charts::ChartService; +use tracing::warn; use user::UserService; impl From for Status { @@ -20,7 +24,26 @@ pub async fn run_server(ctx: Context) -> Result<(), Box> let verifier = JwtVerifier::from_secret(&ctx.config.jwt_secret)?; let addr: SocketAddr = ctx.config.socket().parse()?; - Server::builder() + let cert_path = ctx.config.tls_cert_path.clone(); + let key_path = ctx.config.tls_key_path.clone(); + + let builder = match (cert_path, key_path) { + (Some(cert_path), Some(key_path)) => { + let cert = read_to_string(cert_path)?; + let key = read_to_string(key_path)?; + let identity = Identity::from_pem(cert, key); + Server::builder().tls_config(ServerTlsConfig::new().identity(identity))? + } + (Some(_), None) | (None, Some(_)) => { + panic!("Both TLS certificate and key must be provided, or neither."); + } + (None, None) => { + warn!("TLS is not configured as the environment variables are not set."); + Server::builder() + } + }; + + builder .layer(AuthLayer::new(verifier)) .add_service(RatingService::new_server()) .add_service(ChartService::new_server()) From 7d93b4576b6b59a7382b5fd418656577cfa5cb12 Mon Sep 17 00:00:00 2001 From: Matthew Hagemann Date: Tue, 26 Nov 2024 17:34:38 +0200 Subject: [PATCH 2/3] style: variable renaming to match actual use --- src/config.rs | 6 +++--- src/context.rs | 1 + src/grpc/mod.rs | 14 +++++++------- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/config.rs b/src/config.rs index cd2b41c4..c07ef643 100644 --- a/src/config.rs +++ b/src/config.rs @@ -16,9 +16,9 @@ pub struct Config { pub jwt_secret: SecretString, /// The base URI for snapcraft.io pub snapcraft_io_uri: String, - /// The path to the tls certificate - pub tls_cert_path: Option, - /// The path to the tls key + /// The path to the tls keychain + pub tls_keychain_path: Option, + /// The path to the tls private key pub tls_key_path: Option, } diff --git a/src/context.rs b/src/context.rs index 375f570d..2244df0e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -10,6 +10,7 @@ pub struct Context { pub config: Config, pub jwt_encoder: JwtEncoder, pub http_client: reqwest::Client, + /// In progress category updates that we need to block on pub category_updates: Mutex>>, } diff --git a/src/grpc/mod.rs b/src/grpc/mod.rs index bc39c014..a5e06423 100644 --- a/src/grpc/mod.rs +++ b/src/grpc/mod.rs @@ -1,4 +1,4 @@ -use crate::{config, db, jwt::JwtVerifier, middleware::AuthLayer, Context}; +use crate::{db, jwt::JwtVerifier, middleware::AuthLayer, Context}; use std::{fs::read_to_string, net::SocketAddr}; use tonic::{ transport::{Identity, Server, ServerTlsConfig}, @@ -24,18 +24,18 @@ pub async fn run_server(ctx: Context) -> Result<(), Box> let verifier = JwtVerifier::from_secret(&ctx.config.jwt_secret)?; let addr: SocketAddr = ctx.config.socket().parse()?; - let cert_path = ctx.config.tls_cert_path.clone(); + let keychain_path = ctx.config.tls_keychain_path.clone(); let key_path = ctx.config.tls_key_path.clone(); - let builder = match (cert_path, key_path) { - (Some(cert_path), Some(key_path)) => { - let cert = read_to_string(cert_path)?; + let builder = match (keychain_path, key_path) { + (Some(keychain_path), Some(key_path)) => { + let keychain = read_to_string(keychain_path)?; let key = read_to_string(key_path)?; - let identity = Identity::from_pem(cert, key); + let identity = Identity::from_pem(keychain, key); Server::builder().tls_config(ServerTlsConfig::new().identity(identity))? } (Some(_), None) | (None, Some(_)) => { - panic!("Both TLS certificate and key must be provided, or neither."); + panic!("Both TLS keychain and private key must be provided, or neither."); } (None, None) => { warn!("TLS is not configured as the environment variables are not set."); From 72364fb06acafc6060292ac98655f58ac3f553d6 Mon Sep 17 00:00:00 2001 From: Matthew Hagemann Date: Tue, 26 Nov 2024 17:47:55 +0200 Subject: [PATCH 3/3] style: import re-arangment --- src/grpc/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/grpc/mod.rs b/src/grpc/mod.rs index a5e06423..8494c373 100644 --- a/src/grpc/mod.rs +++ b/src/grpc/mod.rs @@ -4,6 +4,7 @@ use tonic::{ transport::{Identity, Server, ServerTlsConfig}, Status, }; +use tracing::warn; mod app; mod charts; @@ -11,7 +12,6 @@ mod user; use app::RatingService; use charts::ChartService; -use tracing::warn; use user::UserService; impl From for Status {