fix(desktop): accept self-signed certs from configured external goosed host (#8400)

Signed-off-by: jh-block <jhugo@block.xyz>
Co-authored-by: Mathis Rocher <mathis.rocher@corp.ovh.com>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: jh-block <jhugo@block.xyz>
This commit is contained in:
Gandalf_Le_Dev
2026-04-15 21:10:37 +02:00
committed by GitHub
parent cff0992aef
commit 890ad15934
10 changed files with 138 additions and 12 deletions
+6 -2
View File
@@ -5,7 +5,7 @@ use axum::middleware;
use axum_server::Handle;
use goose_server::auth::check_token;
#[cfg(any(feature = "rustls-tls", feature = "native-tls"))]
use goose_server::tls::self_signed_config;
use goose_server::tls::setup_tls;
use tower_http::cors::{Any, CorsLayer};
use tracing::info;
@@ -78,7 +78,11 @@ pub async fn run() -> Result<()> {
if settings.tls {
#[cfg(any(feature = "rustls-tls", feature = "native-tls"))]
{
let tls_setup = self_signed_config().await?;
let tls_setup = setup_tls(
settings.tls_cert_path.as_deref(),
settings.tls_key_path.as_deref(),
)
.await?;
let handle = Handle::new();
let shutdown_handle = handle.clone();
+4
View File
@@ -11,6 +11,8 @@ pub struct Settings {
pub port: u16,
#[serde(default = "default_tls")]
pub tls: bool,
pub tls_cert_path: Option<String>,
pub tls_key_path: Option<String>,
}
impl Settings {
@@ -91,6 +93,8 @@ mod tests {
host: "127.0.0.1".to_string(),
port: 3000,
tls: true,
tls_cert_path: None,
tls_key_path: None,
};
let addr = server_settings.socket_addr();
assert_eq!(addr.to_string(), "127.0.0.1:3000");
+41 -1
View File
@@ -11,8 +11,9 @@
//! / SChannel respectively, but `axum-server` does not offer those backends so
//! the server listener always uses OpenSSL when this feature is active.
use anyhow::Result;
use anyhow::{bail, Result};
use rcgen::{CertificateParams, DnType, KeyPair, SanType};
use std::path::Path;
#[cfg(feature = "rustls-tls")]
pub type TlsConfig = axum_server::tls_rustls::RustlsConfig;
@@ -65,6 +66,45 @@ fn sha256_fingerprint(der: &[u8]) -> String {
}
}
/// Load TLS configuration from user-provided PEM certificate and key files.
///
/// The SHA-256 fingerprint of the leaf certificate is computed and printed to
/// stdout so the parent process (e.g. Electron) can pin it, just like the
/// self-signed path.
pub async fn from_pem_files(cert_path: &Path, key_path: &Path) -> Result<TlsSetup> {
let cert_pem = std::fs::read(cert_path)?;
let key_pem = std::fs::read(key_path)?;
// Parse the first PEM block to extract the DER-encoded certificate for fingerprinting.
let der = pem::parse(&cert_pem)?.into_contents();
let fingerprint = sha256_fingerprint(&der);
println!("GOOSED_CERT_FINGERPRINT={fingerprint}");
#[cfg(feature = "rustls-tls")]
let config = {
let _ = rustls::crypto::aws_lc_rs::default_provider().install_default();
axum_server::tls_rustls::RustlsConfig::from_pem(cert_pem, key_pem.clone()).await?
};
#[cfg(feature = "native-tls")]
let config = axum_server::tls_openssl::OpenSSLConfig::from_pem(&cert_pem, &key_pem)?;
Ok(TlsSetup {
config,
fingerprint,
})
}
/// Set up TLS, using user-provided PEM files if both paths are given,
/// otherwise generating a self-signed certificate.
pub async fn setup_tls(cert_path: Option<&str>, key_path: Option<&str>) -> Result<TlsSetup> {
match (cert_path, key_path) {
(Some(cert), Some(key)) => from_pem_files(Path::new(cert), Path::new(key)).await,
(None, None) => self_signed_config().await,
_ => bail!("Both GOOSE_TLS_CERT_PATH and GOOSE_TLS_KEY_PATH must be set, or neither"),
}
}
/// Generate a self-signed TLS certificate for localhost (127.0.0.1) and
/// return a [`TlsSetup`] containing the server config and the SHA-256
/// fingerprint of the generated certificate (colon-separated hex).