Implement federation self-test

This commit is contained in:
Lambda 2024-09-20 12:05:24 +00:00 committed by Benjamin Lee
parent 6022d56094
commit e14b7f28f2
No known key found for this signature in database
GPG key ID: FB9624E2885D55A4
4 changed files with 46 additions and 3 deletions

View file

@ -254,3 +254,5 @@ This will be the first release of Grapevine since it was forked from Conduit
21. Sending SIGHUP to the grapevine process now reloads TLS certificates from 21. Sending SIGHUP to the grapevine process now reloads TLS certificates from
disk. disk.
([!97](https://gitlab.computer.surgery/matrix/grapevine-fork/-/merge_requests/97)) ([!97](https://gitlab.computer.surgery/matrix/grapevine-fork/-/merge_requests/97))
22. Added a federation self-test, perfomed automatically on startup.
([!106](https://gitlab.computer.surgery/matrix/grapevine/-/merge_requests/106))

View file

@ -22,6 +22,7 @@ use ruma::api::{
error::{Error as RumaError, ErrorBody, ErrorKind}, error::{Error as RumaError, ErrorBody, ErrorKind},
uiaa::UiaaResponse, uiaa::UiaaResponse,
}, },
federation::discovery::get_server_version,
IncomingRequest, IncomingRequest,
}; };
use tokio::{signal, task::JoinSet}; use tokio::{signal, task::JoinSet};
@ -38,7 +39,8 @@ use crate::{
api::{ api::{
client_server, client_server,
ruma_wrapper::{Ar, Ra}, ruma_wrapper::{Ar, Ra},
server_server, well_known, server_server::{self, AllowLoopbackRequests, LogRequestError},
well_known,
}, },
config::{self, Config, ListenComponent, ListenTransport}, config::{self, Config, ListenComponent, ListenTransport},
database::KeyValueDatabase, database::KeyValueDatabase,
@ -98,6 +100,30 @@ pub(crate) async fn run(args: ServeArgs) -> Result<(), error::ServeCommand> {
Ok(()) Ok(())
} }
#[tracing::instrument]
async fn federation_self_test() -> Result<()> {
let response = server_server::send_request(
&services().globals.config.server_name,
get_server_version::v1::Request {},
LogRequestError::Yes,
AllowLoopbackRequests::Yes,
)
.await?;
if !response
.server
.as_ref()
.is_some_and(|s| s.name.as_deref() == Some(env!("CARGO_PKG_NAME")))
{
error!(?response, "unexpected server version");
return Err(Error::BadConfig(
"Got unexpected version from our own version endpoint",
));
}
Ok(())
}
#[allow(clippy::too_many_lines)] #[allow(clippy::too_many_lines)]
async fn run_server() -> Result<(), error::Serve> { async fn run_server() -> Result<(), error::Serve> {
use error::Serve as Error; use error::Serve as Error;
@ -226,10 +252,17 @@ async fn run_server() -> Result<(), error::Serve> {
} }
} }
set_application_state(ApplicationState::Ready);
tokio::spawn(handle_signals(tls_config, handles)); tokio::spawn(handle_signals(tls_config, handles));
if config.federation.enable && config.federation.self_test {
federation_self_test()
.await
.map_err(error::Serve::FederationSelfTestFailed)?;
debug!("Federation self-test completed successfully");
}
set_application_state(ApplicationState::Ready);
while let Some(result) = servers.join_next().await { while let Some(result) = servers.join_next().await {
let (listen, result) = let (listen, result) =
result.expect("should be able to join server task"); result.expect("should be able to join server task");

View file

@ -328,6 +328,7 @@ pub(crate) struct ObservabilityConfig {
#[serde(default)] #[serde(default)]
pub(crate) struct FederationConfig { pub(crate) struct FederationConfig {
pub(crate) enable: bool, pub(crate) enable: bool,
pub(crate) self_test: bool,
pub(crate) trusted_servers: Vec<OwnedServerName>, pub(crate) trusted_servers: Vec<OwnedServerName>,
pub(crate) max_fetch_prev_events: u16, pub(crate) max_fetch_prev_events: u16,
pub(crate) max_concurrent_requests: u16, pub(crate) max_concurrent_requests: u16,
@ -338,6 +339,7 @@ impl Default for FederationConfig {
fn default() -> Self { fn default() -> Self {
Self { Self {
enable: true, enable: true,
self_test: true,
trusted_servers: vec![ trusted_servers: vec![
OwnedServerName::try_from("matrix.org").unwrap() OwnedServerName::try_from("matrix.org").unwrap()
], ],

View file

@ -160,4 +160,10 @@ pub(crate) enum Serve {
#[error("failed to run request listener on {1}")] #[error("failed to run request listener on {1}")]
Listen(#[source] std::io::Error, ListenConfig), Listen(#[source] std::io::Error, ListenConfig),
#[error(
"federation self-test failed (set `federation.self_test = false` in \
config to disable)"
)]
FederationSelfTestFailed(#[source] crate::Error),
} }