distill active and old keys for federation key/server response
Signed-off-by: Jason Volk <jason@zemos.net>
This commit is contained in:
parent
c769fcc347
commit
aa768b5dec
2 changed files with 47 additions and 10 deletions
|
@ -1,10 +1,14 @@
|
||||||
use std::{collections::BTreeMap, time::Duration};
|
use std::{
|
||||||
|
collections::BTreeMap,
|
||||||
|
mem::take,
|
||||||
|
time::{Duration, SystemTime},
|
||||||
|
};
|
||||||
|
|
||||||
use axum::{extract::State, response::IntoResponse, Json};
|
use axum::{extract::State, response::IntoResponse, Json};
|
||||||
use conduit::{utils::timepoint_from_now, Result};
|
use conduit::{utils::timepoint_from_now, Result};
|
||||||
use ruma::{
|
use ruma::{
|
||||||
api::{
|
api::{
|
||||||
federation::discovery::{get_server_keys, ServerSigningKeys},
|
federation::discovery::{get_server_keys, OldVerifyKey, ServerSigningKeys},
|
||||||
OutgoingResponse,
|
OutgoingResponse,
|
||||||
},
|
},
|
||||||
serde::Raw,
|
serde::Raw,
|
||||||
|
@ -21,21 +25,32 @@ use ruma::{
|
||||||
// signature for the response
|
// signature for the response
|
||||||
pub(crate) async fn get_server_keys_route(State(services): State<crate::State>) -> Result<impl IntoResponse> {
|
pub(crate) async fn get_server_keys_route(State(services): State<crate::State>) -> Result<impl IntoResponse> {
|
||||||
let server_name = services.globals.server_name();
|
let server_name = services.globals.server_name();
|
||||||
let verify_keys = services.server_keys.verify_keys_for(server_name).await;
|
let active_key_id = services.server_keys.active_key_id();
|
||||||
|
let mut all_keys = services.server_keys.verify_keys_for(server_name).await;
|
||||||
|
|
||||||
|
let verify_keys = all_keys
|
||||||
|
.remove_entry(active_key_id)
|
||||||
|
.expect("active verify_key is missing");
|
||||||
|
|
||||||
|
let old_verify_keys = all_keys
|
||||||
|
.into_iter()
|
||||||
|
.map(|(id, key)| (id, OldVerifyKey::new(expires_ts(), key.key)))
|
||||||
|
.collect();
|
||||||
|
|
||||||
let server_key = ServerSigningKeys {
|
let server_key = ServerSigningKeys {
|
||||||
verify_keys,
|
verify_keys: [verify_keys].into(),
|
||||||
|
old_verify_keys,
|
||||||
server_name: server_name.to_owned(),
|
server_name: server_name.to_owned(),
|
||||||
valid_until_ts: valid_until_ts(),
|
valid_until_ts: valid_until_ts(),
|
||||||
old_verify_keys: BTreeMap::new(),
|
|
||||||
signatures: BTreeMap::new(),
|
signatures: BTreeMap::new(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let response = get_server_keys::v2::Response {
|
let server_key = Raw::new(&server_key)?;
|
||||||
server_key: Raw::new(&server_key)?,
|
let mut response = get_server_keys::v2::Response::new(server_key)
|
||||||
}
|
.try_into_http_response::<Vec<u8>>()
|
||||||
.try_into_http_response::<Vec<u8>>()?;
|
.map(|mut response| take(response.body_mut()))
|
||||||
|
.and_then(|body| serde_json::from_slice(&body).map_err(Into::into))?;
|
||||||
|
|
||||||
let mut response = serde_json::from_slice(response.body())?;
|
|
||||||
services.server_keys.sign_json(&mut response)?;
|
services.server_keys.sign_json(&mut response)?;
|
||||||
|
|
||||||
Ok(Json(response))
|
Ok(Json(response))
|
||||||
|
@ -47,6 +62,11 @@ fn valid_until_ts() -> MilliSecondsSinceUnixEpoch {
|
||||||
MilliSecondsSinceUnixEpoch::from_system_time(timepoint).expect("UInt should not overflow")
|
MilliSecondsSinceUnixEpoch::from_system_time(timepoint).expect("UInt should not overflow")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn expires_ts() -> MilliSecondsSinceUnixEpoch {
|
||||||
|
let timepoint = SystemTime::now();
|
||||||
|
MilliSecondsSinceUnixEpoch::from_system_time(timepoint).expect("UInt should not overflow")
|
||||||
|
}
|
||||||
|
|
||||||
/// # `GET /_matrix/key/v2/server/{keyId}`
|
/// # `GET /_matrix/key/v2/server/{keyId}`
|
||||||
///
|
///
|
||||||
/// Gets the public signing keys of this server.
|
/// Gets the public signing keys of this server.
|
||||||
|
|
|
@ -44,7 +44,9 @@ pub type PubKeys = PublicKeySet;
|
||||||
impl crate::Service for Service {
|
impl crate::Service for Service {
|
||||||
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
|
fn build(args: crate::Args<'_>) -> Result<Arc<Self>> {
|
||||||
let minimum_valid = Duration::from_secs(3600);
|
let minimum_valid = Duration::from_secs(3600);
|
||||||
|
|
||||||
let (keypair, verify_keys) = keypair::init(args.db)?;
|
let (keypair, verify_keys) = keypair::init(args.db)?;
|
||||||
|
debug_assert!(verify_keys.len() == 1, "only one active verify_key supported");
|
||||||
|
|
||||||
Ok(Arc::new(Self {
|
Ok(Arc::new(Self {
|
||||||
keypair,
|
keypair,
|
||||||
|
@ -68,6 +70,21 @@ impl crate::Service for Service {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn keypair(&self) -> &Ed25519KeyPair { &self.keypair }
|
pub fn keypair(&self) -> &Ed25519KeyPair { &self.keypair }
|
||||||
|
|
||||||
|
#[implement(Service)]
|
||||||
|
#[inline]
|
||||||
|
pub fn active_key_id(&self) -> &ServerSigningKeyId { self.active_verify_key().0 }
|
||||||
|
|
||||||
|
#[implement(Service)]
|
||||||
|
#[inline]
|
||||||
|
pub fn active_verify_key(&self) -> (&ServerSigningKeyId, &VerifyKey) {
|
||||||
|
debug_assert!(self.verify_keys.len() <= 1, "more than one active verify_key");
|
||||||
|
self.verify_keys
|
||||||
|
.iter()
|
||||||
|
.next()
|
||||||
|
.map(|(id, key)| (id.as_ref(), key))
|
||||||
|
.expect("missing active verify_key")
|
||||||
|
}
|
||||||
|
|
||||||
#[implement(Service)]
|
#[implement(Service)]
|
||||||
async fn add_signing_keys(&self, new_keys: ServerSigningKeys) {
|
async fn add_signing_keys(&self, new_keys: ServerSigningKeys) {
|
||||||
let origin = &new_keys.server_name;
|
let origin = &new_keys.server_name;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue