Skip to content

brokkr-broker::utils

Rust

Utility functions and structures for the Brokkr broker.

This module contains various helper functions and structures used throughout the broker, including admin key management and shutdown procedures.

pub

Derives: Queryable, Selectable, Identifiable, AsChangeset, Debug, Clone

Represents an admin key in the database.

Name Type Description
id Uuid
created_at chrono::DateTime<Utc>
updated_at chrono::DateTime<Utc>
pak_hash String

pub

Derives: Insertable

Represents a new admin key to be inserted into the database.

Name Type Description
pak_hash String

pub

Derives: Debug, Clone, Copy, PartialEq, Eq

Which admin credential sources still carry the shipped default hash.

The two are tracked separately because they have different causes and different fixes. configured is the live config value; stored is what is actually in admin_role.pak_hash — and those can disagree, because upsert_admin only runs on first startup (or an explicit rotate admin). An install that first booted with the default and later had BROKKR__BROKER__PAK_HASH set keeps accepting the public PAK until the admin row is rotated, which is the case a config-only check would miss.

Name Type Description
configured bool The configured broker.pak_hash is the shipped default.
stored bool The admin hash stored in the database is the shipped default.

pub

fn in_use(&self) -> bool

True when the publicly-known PAK is accepted as admin by this broker.

Source
pub fn in_use(&self) -> bool {
self.configured || self.stored
}

pub

What upsert_admin actually did.

The two branches look identical from the outside — both end with a hash on admin_role and the admin generator — but only one produces a new credential. rotate admin reports “rotated successfully” for both unless it is told them apart, which is misleading on the branch that mints nothing (BROKKR-T-0317).

  • Minted - No hash was configured, so a fresh PAK was minted. The plaintext is returned and written to BOOTSTRAP_KEY_FILE; it cannot be recovered from the hash afterwards.
  • ReappliedConfigured - broker.pak_hash was set, so it was validated and re-applied verbatim. No credential was created and whatever PAK matches that hash keeps working — including, on a default install, the publicly-known one.

pub

async fn shutdown(shutdown_rx: oneshot::Receiver<()>)

Handles the shutdown process for the broker.

This function waits for a shutdown signal and then performs cleanup tasks.

Source
pub async fn shutdown(shutdown_rx: oneshot::Receiver<()>) {
let _ = shutdown_rx.await;
// Remove the bootstrap key file dropped by `upsert_admin` on first startup.
let _ = fs::remove_file(BOOTSTRAP_KEY_FILE);
}

pub

fn first_startup(
conn: &mut PgConnection,
config: &Settings,
) -> Result<(), Box<dyn std::error::Error>>

Performs first-time startup operations.

This function is called when the broker starts for the first time and sets up the initial admin key.

Source
pub fn first_startup(
conn: &mut PgConnection,
config: &Settings,
) -> Result<(), Box<dyn std::error::Error>> {
// `serve` deliberately does not surface the PAK on stdout: it is a
// long-running process whose output is a log stream, and a secret written
// there would persist in `kubectl logs` for the pod's lifetime. The
// bootstrap key file remains that path's channel.
upsert_admin(conn, config).map(|_| ())
}

pub

fn upsert_admin(
conn: &mut PgConnection,
config: &Settings,
) -> Result<AdminPakOutcome, Box<dyn std::error::Error>>

Updates or inserts the admin key and related generator.

This function creates or updates the admin key in the database, creates or updates the associated admin generator, and writes the PAK to a temporary file.

Source
pub fn upsert_admin(
conn: &mut PgConnection,
config: &Settings,
) -> Result<AdminPakOutcome, Box<dyn std::error::Error>> {
let outcome = match &config.broker.pak_hash {
Some(hash) if !hash.is_empty() => {
// Validate the provided hash
if !validate_pak_hash(hash) {
return Err("Invalid PAK hash provided in configuration".into());
}
AdminPakOutcome::ReappliedConfigured { hash: hash.clone() }
}
_ => {
// Generate new PAK and hash
let (pak, hash) = create_pak()?;
// Write PAK to temporary file. Retained as the channel for
// `serve`'s first startup, which cannot print secrets; `rotate
// admin` also returns the plaintext so it can be shown directly.
info!("Writing PAK to temporary file");
let key_path = Path::new(BOOTSTRAP_KEY_FILE);
fs::create_dir_all(key_path.parent().unwrap())?;
fs::write(key_path, &pak)?;
AdminPakOutcome::Minted { pak, hash }
}
};
let pak_hash = match &outcome {
AdminPakOutcome::Minted { hash, .. } => hash.clone(),
AdminPakOutcome::ReappliedConfigured { hash } => hash.clone(),
};
// Update or insert admin key
let existing_admin_key = admin_role::table
.select(admin_role::id)
.first::<Uuid>(conn)
.optional()?;
match existing_admin_key {
Some(id) => {
diesel::update(admin_role::table.find(id))
.set(admin_role::pak_hash.eq(&pak_hash))
.execute(conn)?;
}
None => {
diesel::insert_into(admin_role::table)
.values(&NewAdminKey {
pak_hash: pak_hash.clone(),
})
.execute(conn)?;
}
}
// Update or insert admin generator
use brokkr_models::schema::generators;
let existing_admin_generator = generators::table
.filter(generators::name.eq("admin-generator"))
.select(generators::id)
.first::<Uuid>(conn)
.optional()?;
match existing_admin_generator {
Some(id) => {
diesel::update(generators::table.find(id))
.set((
generators::pak_hash.eq(&pak_hash),
generators::description.eq("Linked to Admin PAK"),
))
.execute(conn)?;
}
None => {
diesel::insert_into(generators::table)
.values((
generators::name.eq("admin-generator"),
generators::description.eq("Linked to Admin PAK"),
generators::pak_hash.eq(&pak_hash),
))
.execute(conn)?;
}
}
Ok(outcome)
}

fn detect_​default_​admin_​pak_​hash

Section titled “fn detect_​default_​admin_​pak_​hash”

pub

fn detect_default_admin_pak_hash(
configured: Option<&str>,
stored: Option<&str>,
) -> DefaultAdminPakStatus

Compares the effective admin credential against the shipped default.

Pure and exact: byte equality against DEFAULT_ADMIN_PAK_HASH, no heuristics, no I/O. serve binds a port and installs process-global state, so the decision lives here where it can be tested directly.

Parameters:

Name Type Description
configured Option<&str> config.broker.pak_hash after the full config layering.
stored Option<&str> admin_role.pak_hash as currently persisted, if the row exists.
Source
pub fn detect_default_admin_pak_hash(
configured: Option<&str>,
stored: Option<&str>,
) -> DefaultAdminPakStatus {
DefaultAdminPakStatus {
configured: configured == Some(DEFAULT_ADMIN_PAK_HASH),
stored: stored == Some(DEFAULT_ADMIN_PAK_HASH),
}
}

pub

fn stored_admin_pak_hash(
conn: &mut PgConnection,
) -> QueryResult<Option<String>>

Reads the persisted admin PAK hash, if the admin role has been provisioned.

Runs against whatever schema the connection’s search_path selects, so on a multi-tenant install it reports the tenant the broker is actually serving.

Source
pub fn stored_admin_pak_hash(conn: &mut PgConnection) -> QueryResult<Option<String>> {
admin_role::table
.select(admin_role::pak_hash)
.first::<String>(conn)
.optional()
}

fn report_​default_​admin_​pak_​hash

Section titled “fn report_​default_​admin_​pak_​hash”

pub

fn report_default_admin_pak_hash(status: &DefaultAdminPakStatus)

Logs the default-admin-PAK banner (if applicable) and publishes brokkr_default_admin_pak_hash_in_use.

Always sets the gauge, including to 0, so the metric is present and alertable on a correctly-configured broker rather than only appearing on a broken one.

Source
pub fn report_default_admin_pak_hash(status: &DefaultAdminPakStatus) {
DEFAULT_ADMIN_PAK_HASH_IN_USE.set(i64::from(status.in_use()));
match default_admin_pak_warning(status) {
Some(banner) => warn!("{}", banner),
None => info!("Admin PAK hash is not the shipped default"),
}
}

fn start_​default_​admin_​pak_​reminder_​task

Section titled “fn start_​default_​admin_​pak_​reminder_​task”

pub

fn start_default_admin_pak_reminder_task(status: DefaultAdminPakStatus)

Spawns the hourly re-warning task described on DEFAULT_ADMIN_PAK_REMINDER_INTERVAL. No-op when the default is not in use, so a correctly-configured broker carries no extra task.

Must be called from within a Tokio runtime.

Source
pub fn start_default_admin_pak_reminder_task(status: DefaultAdminPakStatus) {
let Some(banner) = default_admin_pak_warning(&status) else {
return;
};
tokio::spawn(async move {
loop {
tokio::time::sleep(DEFAULT_ADMIN_PAK_REMINDER_INTERVAL).await;
warn!("{}", banner);
}
});
}