fix: harden fips startup and app port relays
This commit is contained in:
@@ -54,7 +54,8 @@ pub async fn ensure_activated(data_dir: &std::path::Path) {
|
||||
tracing::warn!("FIPS auto-activate: config install failed: {:#}", e);
|
||||
return;
|
||||
}
|
||||
if let Err(e) = service::activate(SERVICE_UNIT).await {
|
||||
let unit = service::activation_unit().await;
|
||||
if let Err(e) = service::activate(unit).await {
|
||||
tracing::warn!("FIPS auto-activate: service activate failed: {:#}", e);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -32,6 +32,16 @@ pub async fn unit_state(unit: &str) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether systemd knows about `unit`.
|
||||
pub async fn unit_exists(unit: &str) -> bool {
|
||||
Command::new("systemctl")
|
||||
.args(["cat", unit])
|
||||
.output()
|
||||
.await
|
||||
.map(|out| out.status.success())
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Whether the `fips` debian package is installed on the host.
|
||||
pub async fn package_installed() -> bool {
|
||||
// dpkg-query -W -f='${Status}' fips → "install ok installed" when present.
|
||||
@@ -131,17 +141,28 @@ done
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Resolve which systemd unit is actually supervising the fips daemon
|
||||
/// on this host. Nodes installed from the archipelago ISO run
|
||||
/// `archipelago-fips.service`; nodes that were apt-installed (or had
|
||||
/// fips running before archipelago took over) may only have the
|
||||
/// upstream `fips.service`. Restart/Reconnect must operate on whichever
|
||||
/// one is running, otherwise the UI button is a silent no-op.
|
||||
/// Resolve which systemd unit should be started when FIPS is inactive.
|
||||
/// Newer Archipelago images may ship `archipelago-fips.service`; nodes with
|
||||
/// the upstream Debian package may only have `fips.service`. Activation must
|
||||
/// choose a unit systemd can actually load, otherwise the dashboard repeatedly
|
||||
/// offers an "Activate" action that can never succeed.
|
||||
pub async fn activation_unit() -> &'static str {
|
||||
if unit_exists(super::SERVICE_UNIT).await {
|
||||
return super::SERVICE_UNIT;
|
||||
}
|
||||
if unit_exists(super::UPSTREAM_SERVICE_UNIT).await {
|
||||
return super::UPSTREAM_SERVICE_UNIT;
|
||||
}
|
||||
super::SERVICE_UNIT
|
||||
}
|
||||
|
||||
/// Resolve which systemd unit is actually supervising the fips daemon on this
|
||||
/// host. Restart/Reconnect must operate on whichever one is running, otherwise
|
||||
/// the UI button is a silent no-op.
|
||||
///
|
||||
/// Returns the archipelago-managed unit name if it's active,
|
||||
/// else the upstream unit name if that's active,
|
||||
/// else the archipelago-managed name as a default (so activate() can
|
||||
/// bring it up).
|
||||
/// else a startable activation unit.
|
||||
pub async fn active_unit() -> &'static str {
|
||||
if unit_state(super::SERVICE_UNIT).await == "active" {
|
||||
return super::SERVICE_UNIT;
|
||||
@@ -149,7 +170,7 @@ pub async fn active_unit() -> &'static str {
|
||||
if unit_state(super::UPSTREAM_SERVICE_UNIT).await == "active" {
|
||||
return super::UPSTREAM_SERVICE_UNIT;
|
||||
}
|
||||
super::SERVICE_UNIT
|
||||
activation_unit().await
|
||||
}
|
||||
|
||||
pub async fn mask(unit: &str) -> Result<()> {
|
||||
@@ -248,4 +269,10 @@ mod tests {
|
||||
// Must not panic regardless of host state.
|
||||
let _ = package_installed().await;
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_unit_exists_is_bool() {
|
||||
// Must not panic regardless of host state.
|
||||
let _ = unit_exists("archipelago-bogus-test.service").await;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user