Fetch User Keys - simple tool for fetching SSH keys from various sources
at master 2.4 kB view raw
1// SPDX-FileCopyrightText: 2024 Łukasz Niemier <#@hauleth.dev> 2// 3// SPDX-License-Identifier: EUPL-1.2 4 5use std::collections::HashMap; 6use std::io::{self, prelude::*}; 7 8use rayon::prelude::*; 9 10#[derive(PartialEq, Eq, Debug, Copy, Clone)] 11pub enum Format { 12 JSON, 13 TOML, 14 CSV, 15 SSH, 16} 17 18impl Format { 19 pub fn render<W: Write>(self, output: &Output, w: &mut W) -> io::Result<()> { 20 match self { 21 Format::JSON => { 22 serde_json::to_writer_pretty(&mut *w, &output.keys).map_err(io::Error::other)?; 23 writeln!(w) 24 } 25 Format::TOML => write!(w, "{}", toml::to_string_pretty(&output.keys).unwrap()), 26 Format::CSV => as_csv(w, output), 27 Format::SSH => authorized_keys(w, output), 28 } 29 } 30} 31 32impl std::fmt::Display for Format { 33 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 34 match *self { 35 Format::JSON => f.write_str("json"), 36 Format::TOML => f.write_str("toml"), 37 Format::CSV => f.write_str("csv"), 38 Format::SSH => f.write_str("ssh"), 39 } 40 } 41} 42 43impl<'a> From<&'a str> for Format { 44 fn from(s: &'a str) -> Format { 45 match s { 46 "json" => Format::JSON, 47 "toml" => Format::TOML, 48 "csv" => Format::CSV, 49 "ssh" => Format::SSH, 50 _ => unreachable!(), 51 } 52 } 53} 54 55#[derive(Debug, serde::Serialize)] 56pub struct Output { 57 pub keys: HashMap<String, Vec<ssh_key::PublicKey>>, 58} 59 60impl FromParallelIterator<(String, Vec<ssh_key::PublicKey>)> for Output { 61 fn from_par_iter<T>(iter: T) -> Self 62 where 63 T: IntoParallelIterator<Item = (String, Vec<ssh_key::PublicKey>)>, 64 { 65 Output { 66 keys: iter.into_par_iter().collect(), 67 } 68 } 69} 70 71// TODO: proper escaping 72fn as_csv<W: Write>(w: &mut W, output: &Output) -> io::Result<()> { 73 for (name, keys) in &output.keys { 74 for key in keys { 75 writeln!(w, "{name},{}", key.to_string())?; 76 } 77 } 78 79 Ok(()) 80} 81 82fn authorized_keys<W: Write>(w: &mut W, output: &Output) -> io::Result<()> { 83 for (name, keys) in &output.keys { 84 for key in keys { 85 let commented = ssh_key::PublicKey::new(key.key_data().clone(), name); 86 writeln!(w, "{}", commented.to_string())?; 87 } 88 } 89 90 Ok(()) 91}