keep the matrix appservice registration in bao, with the host file as the last copy
This commit is contained in:
parent
fb6cd36b5f
commit
d5c5862654
1 changed files with 1014 additions and 273 deletions
|
|
@ -129,6 +129,44 @@ pub fn swarm_appservice_token_path() -> Result<String, Error> {
|
|||
Ok(format!("{prefix}/matrix/appservice-token"))
|
||||
}
|
||||
|
||||
/// The path holding the swarm appservice's registration: the `as_token` and
|
||||
/// `hs_token` the homeserver loads.
|
||||
///
|
||||
/// The store is the source of truth for both tokens. The matrix container keeps a
|
||||
/// copy on disk that the homeserver starts from, and derives
|
||||
/// [`swarm_appservice_token_path`] from the `as_token` here for
|
||||
/// `swarm-controller`. It sits beside that path, under the one kind no hive's
|
||||
/// policy reads, for the same reason.
|
||||
///
|
||||
/// # Errors
|
||||
/// Never in practice: the name segment is a constant. The `Result` is
|
||||
/// [`principal_prefix`]'s.
|
||||
pub fn swarm_appservice_registration_path() -> Result<String, Error> {
|
||||
let prefix = principal_prefix(Kind::Controller, CONTROLLER)?;
|
||||
Ok(format!("{prefix}/matrix/appservice-registration"))
|
||||
}
|
||||
|
||||
/// What [`swarm_appservice_registration_path`] holds. The registration's
|
||||
/// namespaces are configuration rendered by nix, not part of it.
|
||||
///
|
||||
/// No `Debug` derive: both fields authenticate to the homeserver.
|
||||
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct Registration {
|
||||
/// The token the appservice presents to the homeserver.
|
||||
pub as_token: String,
|
||||
/// The token the homeserver presents to the appservice.
|
||||
pub hs_token: String,
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Registration {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("Registration")
|
||||
.field("as_token", &"<redacted>")
|
||||
.field("hs_token", &"<redacted>")
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// What an account's path holds: the token, plus the homeserver it belongs to.
|
||||
///
|
||||
/// The homeserver rides with the token because the agent's daemon learns both
|
||||
|
|
@ -266,6 +304,28 @@ mod tests {
|
|||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn the_swarm_appservice_registration_lands_beside_its_token() {
|
||||
assert_eq!(
|
||||
swarm_appservice_registration_path().expect("a constant segment"),
|
||||
"swarm/controller/swarm-controller/matrix/appservice-registration"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_registration_debug_prints_no_token() {
|
||||
let r = Registration {
|
||||
as_token: "as-secret".to_owned(),
|
||||
hs_token: "hs-secret".to_owned(),
|
||||
};
|
||||
let shown = format!("{r:?}");
|
||||
assert!(
|
||||
!shown.contains("as-secret") && !shown.contains("hs-secret"),
|
||||
"{shown}"
|
||||
);
|
||||
assert!(shown.contains("Registration"), "{shown}");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn no_hive_policy_reaches_the_swarm_appservice_token() {
|
||||
// 🩸 The swarm's sender is a homeserver admin, so its token must not
|
||||
|
|
@ -280,8 +340,12 @@ mod tests {
|
|||
.filter_map(|p| p.strip_suffix("*\" {"))
|
||||
.collect();
|
||||
let reads = |path: &str| granted.iter().any(|g| path.starts_with(g));
|
||||
let path = swarm_appservice_token_path().expect("a constant segment");
|
||||
assert!(!reads(&path), "{path} is readable under {granted:?}");
|
||||
for path in [
|
||||
swarm_appservice_token_path().expect("a constant segment"),
|
||||
swarm_appservice_registration_path().expect("a constant segment"),
|
||||
] {
|
||||
assert!(!reads(&path), "{path} is readable under {granted:?}");
|
||||
}
|
||||
// The control: an agent's account path IS under a hive stanza, so the
|
||||
// assertion above can fail at all.
|
||||
let agent = account_path("atlas", "main").expect("legal");
|
||||
|
|
|
|||
Loading…
Reference in a new issue