feat(rustproxy): support dynamically loaded TLS certificates via loadCertificate IPC and include them in listener TLS configs for rebuilds and hot-swap
This commit is contained in:
@@ -1,5 +1,12 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2026-02-16 - 25.4.0 - feat(rustproxy)
|
||||||
|
support dynamically loaded TLS certificates via loadCertificate IPC and include them in listener TLS configs for rebuilds and hot-swap
|
||||||
|
|
||||||
|
- Adds loaded_certs: HashMap<String, TlsCertConfig> to RustProxy to store certificates loaded at runtime
|
||||||
|
- Merge loaded_certs into tls_configs in rebuild and listener hot-swap paths so dynamically loaded certs are served immediately
|
||||||
|
- Persist loaded certificates on loadCertificate so future rebuilds include them
|
||||||
|
|
||||||
## 2026-02-15 - 25.3.1 - fix(plugins)
|
## 2026-02-15 - 25.3.1 - fix(plugins)
|
||||||
remove unused dependencies and simplify plugin exports
|
remove unused dependencies and simplify plugin exports
|
||||||
|
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ pub struct RustProxy {
|
|||||||
started_at: Option<Instant>,
|
started_at: Option<Instant>,
|
||||||
/// Shared path to a Unix domain socket for relaying socket-handler connections back to TypeScript.
|
/// Shared path to a Unix domain socket for relaying socket-handler connections back to TypeScript.
|
||||||
socket_handler_relay: Arc<std::sync::RwLock<Option<String>>>,
|
socket_handler_relay: Arc<std::sync::RwLock<Option<String>>>,
|
||||||
|
/// Dynamically loaded certificates (via loadCertificate IPC), independent of CertManager.
|
||||||
|
loaded_certs: HashMap<String, TlsCertConfig>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RustProxy {
|
impl RustProxy {
|
||||||
@@ -118,6 +120,7 @@ impl RustProxy {
|
|||||||
started: false,
|
started: false,
|
||||||
started_at: None,
|
started_at: None,
|
||||||
socket_handler_relay: Arc::new(std::sync::RwLock::new(None)),
|
socket_handler_relay: Arc::new(std::sync::RwLock::new(None)),
|
||||||
|
loaded_certs: HashMap::new(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,6 +271,13 @@ impl RustProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge dynamically loaded certs (from loadCertificate IPC)
|
||||||
|
for (d, c) in &self.loaded_certs {
|
||||||
|
if !tls_configs.contains_key(d) {
|
||||||
|
tls_configs.insert(d.clone(), c.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if !tls_configs.is_empty() {
|
if !tls_configs.is_empty() {
|
||||||
debug!("Loaded TLS certificates for {} domains", tls_configs.len());
|
debug!("Loaded TLS certificates for {} domains", tls_configs.len());
|
||||||
listener.set_tls_configs(tls_configs);
|
listener.set_tls_configs(tls_configs);
|
||||||
@@ -576,6 +586,12 @@ impl RustProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Merge dynamically loaded certs (from loadCertificate IPC)
|
||||||
|
for (d, c) in &self.loaded_certs {
|
||||||
|
if !tls_configs.contains_key(d) {
|
||||||
|
tls_configs.insert(d.clone(), c.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
listener.set_tls_configs(tls_configs);
|
listener.set_tls_configs(tls_configs);
|
||||||
|
|
||||||
// Add new ports
|
// Add new ports
|
||||||
@@ -786,6 +802,12 @@ impl RustProxy {
|
|||||||
cm.load_static(domain.to_string(), bundle);
|
cm.load_static(domain.to_string(), bundle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Persist in loaded_certs so future rebuild calls include this cert
|
||||||
|
self.loaded_certs.insert(domain.to_string(), TlsCertConfig {
|
||||||
|
cert_pem: cert_pem.clone(),
|
||||||
|
key_pem: key_pem.clone(),
|
||||||
|
});
|
||||||
|
|
||||||
// Hot-swap TLS config on the listener
|
// Hot-swap TLS config on the listener
|
||||||
if let Some(ref mut listener) = self.listener_manager {
|
if let Some(ref mut listener) = self.listener_manager {
|
||||||
let mut tls_configs = Self::extract_tls_configs(&self.options.routes);
|
let mut tls_configs = Self::extract_tls_configs(&self.options.routes);
|
||||||
@@ -809,6 +831,13 @@ impl RustProxy {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Merge dynamically loaded certs from previous loadCertificate calls
|
||||||
|
for (d, c) in &self.loaded_certs {
|
||||||
|
if !tls_configs.contains_key(d) {
|
||||||
|
tls_configs.insert(d.clone(), c.clone());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
listener.set_tls_configs(tls_configs);
|
listener.set_tls_configs(tls_configs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@push.rocks/smartproxy',
|
name: '@push.rocks/smartproxy',
|
||||||
version: '25.3.1',
|
version: '25.4.0',
|
||||||
description: 'A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.'
|
description: 'A powerful proxy package with unified route-based configuration for high traffic management. Features include SSL/TLS support, flexible routing patterns, WebSocket handling, advanced security options, and automatic ACME certificate management.'
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user