proxy: Forward TLS config to client watches (#1087)
This commit adds the initial wiring to forward TLS config changes to the watches used by TLS clients as well as TLS servers. As the TLS clients are not yet implemented, the config type is currently `()`, but once the client config is implemented, we should be able to drop it in seamlessly. Signed-off-by: Eliza Weisman <eliza@buoyant.io> Co-authored-by: Brian Smith <brian@briansmith.org>
This commit is contained in:
parent
d70bb6d06c
commit
0687665444
|
@ -232,7 +232,7 @@ where
|
||||||
|
|
||||||
let bind = Bind::new().with_sensors(sensors.clone());
|
let bind = Bind::new().with_sensors(sensors.clone());
|
||||||
|
|
||||||
let (tls_server_config, tls_cfg_bg) =
|
let (_tls_client_config, tls_server_config, tls_cfg_bg) =
|
||||||
tls::watch_for_config_changes(config.tls_settings.as_ref());
|
tls::watch_for_config_changes(config.tls_settings.as_ref());
|
||||||
|
|
||||||
// Setup the public listener. This will listen on a publicly accessible
|
// Setup the public listener. This will listen on a publicly accessible
|
||||||
|
|
|
@ -14,12 +14,10 @@ use super::{
|
||||||
webpki,
|
webpki,
|
||||||
};
|
};
|
||||||
|
|
||||||
use futures::{future, Future, Sink, Stream};
|
use futures::{future, Future, Stream};
|
||||||
use futures_watch::Watch;
|
use futures_watch::Watch;
|
||||||
use tokio::timer::Interval;
|
use tokio::timer::Interval;
|
||||||
|
|
||||||
pub type ServerConfigWatch = Watch<Option<ServerConfig>>;
|
|
||||||
|
|
||||||
/// Not-yet-validated settings that are used for both TLS clients and TLS
|
/// Not-yet-validated settings that are used for both TLS clients and TLS
|
||||||
/// servers.
|
/// servers.
|
||||||
///
|
///
|
||||||
|
@ -49,11 +47,19 @@ pub struct CommonConfig {
|
||||||
cert_resolver: Arc<CertResolver>,
|
cert_resolver: Arc<CertResolver>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Validated configuration for TLS clients.
|
||||||
|
///
|
||||||
|
/// TODO: Fill this in with the actual configuration.
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
pub struct ClientConfig(Arc<()>);
|
||||||
|
|
||||||
/// Validated configuration for TLS servers.
|
/// Validated configuration for TLS servers.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ServerConfig(pub(super) Arc<rustls::ServerConfig>);
|
pub struct ServerConfig(pub(super) Arc<rustls::ServerConfig>);
|
||||||
|
|
||||||
|
pub type ClientConfigWatch = Watch<Option<ClientConfig>>;
|
||||||
|
pub type ServerConfigWatch = Watch<Option<ServerConfig>>;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
Io(PathBuf, io::Error),
|
Io(PathBuf, io::Error),
|
||||||
|
@ -270,29 +276,47 @@ impl CommonConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn watch_for_config_changes(settings: Option<&CommonSettings>)
|
pub fn watch_for_config_changes(settings: Option<&CommonSettings>)
|
||||||
-> (ServerConfigWatch, Box<Future<Item = (), Error = ()> + Send>)
|
-> (ClientConfigWatch, ServerConfigWatch, Box<Future<Item = (), Error = ()> + Send>)
|
||||||
{
|
{
|
||||||
let settings = if let Some(settings) = settings {
|
let settings = if let Some(settings) = settings {
|
||||||
settings.clone()
|
settings.clone()
|
||||||
} else {
|
} else {
|
||||||
let (watch, _) = Watch::new(None);
|
let (client_watch, _) = Watch::new(None);
|
||||||
|
let (server_watch, _) = Watch::new(None);
|
||||||
let no_future = future::ok(());
|
let no_future = future::ok(());
|
||||||
return (watch, Box::new(no_future));
|
return (client_watch, server_watch, Box::new(no_future));
|
||||||
};
|
};
|
||||||
|
|
||||||
let changes = settings.stream_changes(Duration::from_secs(1));
|
let changes = settings.stream_changes(Duration::from_secs(1));
|
||||||
let (watch, store) = Watch::new(None);
|
let (client_watch, client_store) = Watch::new(None);
|
||||||
let server_configs = changes.map(|ref config| Some(ServerConfig::from(config)));
|
let (server_watch, server_store) = Watch::new(None);
|
||||||
let store = store
|
|
||||||
.sink_map_err(|_| warn!("all server config watches dropped"));
|
// `Store::store` will return an error iff all watchers have been dropped,
|
||||||
let f = server_configs.forward(store)
|
// so we'll use `fold` to cancel the forwarding future. Eventually, we can
|
||||||
.map(|_| trace!("forwarding to server config watch finished."));
|
// also use the fold to continue tracking previous states if we need to do
|
||||||
|
// that.
|
||||||
|
let f = changes
|
||||||
|
.fold(
|
||||||
|
(client_store, server_store),
|
||||||
|
|(mut client_store, mut server_store), ref config| {
|
||||||
|
client_store
|
||||||
|
.store(Some(ClientConfig(Arc::new(()))))
|
||||||
|
.map_err(|_| trace!("all client config watchers dropped"))?;
|
||||||
|
server_store
|
||||||
|
.store(Some(ServerConfig::from(config)))
|
||||||
|
.map_err(|_| trace!("all server config watchers dropped"))?;
|
||||||
|
Ok((client_store, server_store))
|
||||||
|
})
|
||||||
|
.then(|_| {
|
||||||
|
trace!("forwarding to server config watch finished.");
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
|
|
||||||
// This function and `ServerConfig::no_tls` return `Box<Future<...>>`
|
// This function and `ServerConfig::no_tls` return `Box<Future<...>>`
|
||||||
// rather than `impl Future<...>` so that they can have the _same_ return
|
// rather than `impl Future<...>` so that they can have the _same_ return
|
||||||
// types (impl Traits are not the same type unless the original
|
// types (impl Traits are not the same type unless the original
|
||||||
// non-anonymized type was the same).
|
// non-anonymized type was the same).
|
||||||
(watch, Box::new(f))
|
(client_watch, server_watch, Box::new(f))
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ServerConfig {
|
impl ServerConfig {
|
||||||
|
|
Loading…
Reference in New Issue