git.delta.rocks / jrsonnet / refs/commits / 2c5a4bd2d3da

difftreelog

source

cmds/fleet/src/keys.rs1.9 KiBsourcehistory
1use std::str::FromStr;23use crate::host::Config;4use age::Recipient;5use anyhow::{anyhow, Result};6use futures::{StreamExt, TryStreamExt};7use itertools::Itertools;8use tracing::warn;910impl Config {11	pub fn cached_key(&self, host: &str) -> Option<String> {12		let data = self.data();13		let key = data.hosts.get(host).map(|h| &h.encryption_key);14		if let Some(key) = key {15			if key.is_empty() {16				return None;17			}18		}19		key.cloned()20	}21	pub fn update_key(&self, host: &str, key: String) {22		let mut data = self.data_mut();23		let host = data.hosts.entry(host.to_string()).or_default();24		host.encryption_key = key.trim().to_string();25	}2627	pub async fn key(&self, host: &str) -> anyhow::Result<String> {28		if let Some(key) = self.cached_key(host) {29			Ok(key)30		} else {31			warn!("Loading key for {}", host);32			let host = self.host(host).await?;33			let mut cmd = host.cmd("cat").await?;34			cmd.arg("/etc/ssh/ssh_host_ed25519_key.pub");35			let key = cmd.run_string().await?;36			self.update_key(&host.name, key.clone());37			Ok(key)38		}39	}40	/// Insecure, requires root41	pub async fn recipient(&self, host: &str) -> anyhow::Result<impl Recipient> {42		let key = self.key(host).await?;43		age::ssh::Recipient::from_str(&key).map_err(|e| anyhow!("parse recipient error: {:?}", e))44	}4546	pub async fn recipients(&self, hosts: Vec<String>) -> Result<Vec<impl Recipient>> {47		futures::stream::iter(hosts.iter())48			.then(|m| self.recipient(m.as_ref()))49			.try_collect::<Vec<_>>()50			.await51	}5253	#[allow(dead_code)]54	pub async fn orphaned_data(&self) -> Result<Vec<String>> {55		let mut out = Vec::new();56		let host_names = self57			.list_hosts()58			.await?59			.into_iter()60			.map(|h| h.name)61			.collect_vec();62		for hostname in self63			.data()64			.hosts65			.iter()66			.filter(|(_, host)| !host.encryption_key.is_empty())67			.map(|(n, _)| n)68		{69			if !host_names.contains(hostname) {70				out.push(hostname.to_owned())71			}72		}7374		Ok(out)75	}76}