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())