Watch
0
0
Fork
You've already forked hyperhive
0
hyperhive/swarm-secret-client/src/builder.rs
atlas 2fc63d844b name the mint, not the publisher, as the writer of the client secrets
Finishes the sweep of prose that said the publisher unit writes or carries the OIDC client secrets: rust docs, nix comments and option descriptions, test names and docs.
2026-10-30 16:57:58 +01:00

93 lines
3.1 KiB
Rust

//! The swarm builder agreement: where its forge token and its queue client
//! secret live in the store, and what each object holds.
//!
//! swarm-controller mints the forge token; the builder reads it, and its queue
//! client secret, under its own certificate. It also reads the cache push
//! token, which the operator writes. Its read stanza in `swarm-bao.nix` names
//! exactly these three paths.
use serde::{Deserialize, Serialize};
use crate::{
Error,
path::{Kind, principal_prefix},
};
/// The builder's name segment under [`Kind::Service`].
const SERVICE: &str = "builder";
/// The path holding the token of the builder's read-only forge account, as a
/// [`crate::forge::Credential`].
///
/// # Errors
/// Never in practice: the name segment is a constant. The `Result` is
/// [`principal_prefix`]'s.
pub fn forge_token_path() -> Result<String, Error> {
let prefix = principal_prefix(Kind::Service, SERVICE)?;
Ok(format!("{prefix}/forge/token"))
}
/// The path holding the token the builder pushes closures to the binary cache
/// with, as an [`AtticPushToken`]. The operator writes it by hand: the cache is
/// an instance outside the swarm, and no swarm unit mints the token.
///
/// Under the cache's own name segment rather than the builder's, since the
/// token belongs to the cache's tenant.
///
/// # Errors
/// Never in practice: the name segment is a constant. The `Result` is
/// [`principal_prefix`]'s.
pub fn attic_push_token_path() -> Result<String, Error> {
let prefix = principal_prefix(Kind::Service, "attic")?;
Ok(format!("{prefix}/push-token"))
}
/// What [`attic_push_token_path`] holds.
///
/// No `Debug`: `value` writes to the binary cache.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct AtticPushToken {
/// The token, under the field name the operator writes.
pub value: String,
}
/// The path holding the queue client secret of the builder's OIDC client
/// `client_id`, where authelia's mint puts every swarm service's.
///
/// # Errors
/// [`Error::PathSegment`] when `client_id` is not a single path segment.
pub fn client_secret_path(client_id: &str) -> Result<String, Error> {
let prefix = principal_prefix(Kind::Service, client_id)?;
Ok(format!("{prefix}/oidc/client"))
}
/// What [`client_secret_path`] holds.
///
/// No `Debug`: `value` authenticates the builder at the queue.
#[derive(Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct ClientSecret {
/// The secret, under the field name authelia's mint writes.
pub value: String,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_paths_are_the_ones_the_store_grants() {
// Spelled out: `swarm-bao.nix` grants each literal.
assert_eq!(
forge_token_path().expect("a constant segment is legal"),
"swarm/services/builder/forge/token"
);
assert_eq!(
client_secret_path("swarm-builder").expect("a plain id is legal"),
"swarm/services/swarm-builder/oidc/client"
);
assert_eq!(
attic_push_token_path().expect("a constant segment is legal"),
"swarm/services/attic/push-token"
);
}
}