git.delta.rocks / jrsonnet / refs/commits / 15ef984b843b

difftreelog

source

cmds/fleet/src/keys.rs1.8 KiBsourcehistory
1use std::str::FromStr;23use crate::{command::CommandExt, host::Config};4use anyhow::{anyhow, Result};5use tracing::warn;67impl Config {8	pub fn cached_key(&self, host: &str) -> Option<String> {9		let data = self.data();10		let key = data.hosts.get(host).map(|h| &h.encryption_key);11		if let Some(key) = key {12			if key.is_empty() {13				return None;14			}15		}16		key.cloned()17	}18	pub fn update_key(&self, host: &str, key: String) {19		let mut data = self.data_mut();20		let host = data.hosts.entry(host.to_string()).or_default();21		host.encryption_key = key.trim().to_string();22	}2324	pub async fn key(&self, host: &str) -> anyhow::Result<String> {25		if let Some(key) = self.cached_key(host) {26			Ok(key)27		} else {28			warn!("Loading key for {}", host);29			let key = self30				.command_on(host, "cat", false)31				.arg("/etc/ssh/ssh_host_ed25519_key.pub")32				.run_string()33				.await?;34			self.update_key(host, key.clone());35			Ok(key)36		}37	}38	/// Insecure, requires root39	pub async fn identity(&self, host: &str) -> anyhow::Result<age::ssh::Identity> {40		warn!("Loading private key for {host}");41		let key = self42			.command_on(host, "cat", true)43			.arg("/etc/ssh/ssh_host_ed25519_key")44			.run_string()45			.await?;46		Ok(age::ssh::Identity::from_buffer(key.as_bytes(), None)?)47	}48	pub async fn recipient(&self, host: &str) -> anyhow::Result<age::ssh::Recipient> {49		let key = self.key(host).await?;50		age::ssh::Recipient::from_str(&key).map_err(|e| anyhow!("parse recipient error: {:?}", e))51	}5253	pub async fn orphaned_data(&self) -> Result<Vec<String>> {54		let mut out = Vec::new();55		let host_names = self.list_hosts().await?;56		for hostname in self57			.data()58			.hosts59			.iter()60			.filter(|(_, host)| !host.encryption_key.is_empty())61			.map(|(n, _)| n)62		{63			if !host_names.contains(hostname) {64				out.push(hostname.to_owned())65			}66		}6768		Ok(out)69	}70}