Fetch User Keys - simple tool for fetching SSH keys from various sources

ft: improve initial implementation

+649 -48
Cargo.lock
···
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
+
name = "anstream"
+
version = "0.6.11"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5"
+
dependencies = [
+
"anstyle",
+
"anstyle-parse",
+
"anstyle-query",
+
"anstyle-wincon",
+
"colorchoice",
+
"utf8parse",
+
]
+
+
[[package]]
+
name = "anstyle"
+
version = "1.0.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
+
+
[[package]]
+
name = "anstyle-parse"
+
version = "0.2.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c"
+
dependencies = [
+
"utf8parse",
+
]
+
+
[[package]]
+
name = "anstyle-query"
+
version = "1.0.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648"
+
dependencies = [
+
"windows-sys 0.52.0",
+
]
+
+
[[package]]
+
name = "anstyle-wincon"
+
version = "3.0.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7"
+
dependencies = [
+
"anstyle",
+
"windows-sys 0.52.0",
+
]
+
+
[[package]]
name = "async-trait"
version = "0.1.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
+
name = "base16ct"
+
version = "0.2.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
+
+
[[package]]
name = "base64"
version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]]
+
name = "base64ct"
+
version = "1.6.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
+
+
[[package]]
name = "bitflags"
version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
[[package]]
+
name = "block-buffer"
+
version = "0.10.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+
dependencies = [
+
"generic-array",
+
]
+
+
[[package]]
name = "bumpalo"
version = "3.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
+
+
[[package]]
+
name = "byteorder"
+
version = "1.5.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]]
name = "bytes"
···
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
+
name = "cipher"
+
version = "0.4.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
+
dependencies = [
+
"crypto-common",
+
"inout",
+
]
+
+
[[package]]
+
name = "clap"
+
version = "4.4.18"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c"
+
dependencies = [
+
"clap_builder",
+
"clap_derive",
+
]
+
+
[[package]]
+
name = "clap_builder"
+
version = "4.4.18"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7"
+
dependencies = [
+
"anstream",
+
"anstyle",
+
"clap_lex",
+
"strsim",
+
]
+
+
[[package]]
+
name = "clap_derive"
+
version = "4.4.7"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
+
dependencies = [
+
"heck",
+
"proc-macro2",
+
"quote",
+
"syn",
+
]
+
+
[[package]]
+
name = "clap_lex"
+
version = "0.6.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
+
+
[[package]]
+
name = "colorchoice"
+
version = "1.0.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
+
+
[[package]]
+
name = "const-oid"
+
version = "0.9.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
+
+
[[package]]
name = "core-foundation"
version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
[[package]]
+
name = "cpufeatures"
+
version = "0.2.12"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
+
dependencies = [
+
"libc",
+
]
+
+
[[package]]
+
name = "crypto-bigint"
+
version = "0.5.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
+
dependencies = [
+
"generic-array",
+
"rand_core",
+
"subtle",
+
"zeroize",
+
]
+
+
[[package]]
+
name = "crypto-common"
+
version = "0.1.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
+
dependencies = [
+
"generic-array",
+
"typenum",
+
]
+
+
[[package]]
+
name = "der"
+
version = "0.7.8"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c"
+
dependencies = [
+
"const-oid",
+
"zeroize",
+
]
+
+
[[package]]
+
name = "digest"
+
version = "0.10.7"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+
dependencies = [
+
"block-buffer",
+
"const-oid",
+
"crypto-common",
+
"subtle",
+
]
+
+
[[package]]
+
name = "ecdsa"
+
version = "0.16.9"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
+
dependencies = [
+
"der",
+
"digest",
+
"elliptic-curve",
+
"rfc6979",
+
"signature",
+
"spki",
+
]
+
+
[[package]]
+
name = "elliptic-curve"
+
version = "0.13.8"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
+
dependencies = [
+
"base16ct",
+
"crypto-bigint",
+
"digest",
+
"ff",
+
"generic-array",
+
"group",
+
"pkcs8",
+
"rand_core",
+
"sec1",
+
"subtle",
+
"zeroize",
+
]
+
+
[[package]]
name = "encoding_rs"
version = "0.8.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]]
-
name = "erased-serde"
-
version = "0.4.2"
+
name = "errno"
+
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "55d05712b2d8d88102bc9868020c9e5c7a1f5527c452b9b97450a1d006140ba7"
+
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
dependencies = [
-
"serde",
+
"libc",
+
"windows-sys 0.52.0",
]
[[package]]
-
name = "errno"
-
version = "0.3.8"
+
name = "eyre"
+
version = "0.6.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
+
checksum = "7cd915d99f24784cdc19fd37ef22b97e3ff0ae756c7e492e9fbfe897d61e2aec"
dependencies = [
-
"libc",
-
"windows-sys 0.52.0",
+
"indenter",
+
"once_cell",
]
[[package]]
···
version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
+
+
[[package]]
+
name = "ff"
+
version = "0.13.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
+
dependencies = [
+
"rand_core",
+
"subtle",
+
]
[[package]]
name = "fnv"
···
version = "0.1.0"
dependencies = [
"async-trait",
+
"clap",
"futures",
"reqwest",
"serde",
"serde_json",
+
"simple-eyre",
+
"ssh-key",
"tokio",
-
"tokio-stream",
"toml",
-
"typetag",
]
[[package]]
···
]
[[package]]
+
name = "generic-array"
+
version = "0.14.7"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+
dependencies = [
+
"typenum",
+
"version_check",
+
"zeroize",
+
]
+
+
[[package]]
+
name = "getrandom"
+
version = "0.2.12"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
+
dependencies = [
+
"cfg-if",
+
"libc",
+
"wasi",
+
]
+
+
[[package]]
name = "gimli"
version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253"
[[package]]
+
name = "group"
+
version = "0.13.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
+
dependencies = [
+
"ff",
+
"rand_core",
+
"subtle",
+
]
+
+
[[package]]
name = "h2"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]]
+
name = "heck"
+
version = "0.4.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
+
+
[[package]]
name = "hermit-abi"
-
version = "0.3.4"
+
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "5d3d0e0f38255e7fa3cf31335b3a56f05febd18025f4db5ef7a0cfb4f8da651f"
+
checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3"
+
+
[[package]]
+
name = "hmac"
+
version = "0.12.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
+
dependencies = [
+
"digest",
+
]
[[package]]
name = "http"
···
]
[[package]]
+
name = "indenter"
+
version = "0.3.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683"
+
+
[[package]]
name = "indexmap"
version = "2.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
-
name = "inventory"
-
version = "0.3.15"
+
name = "inout"
+
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767"
+
checksum = "a0c10553d664a4d0bcff9f4215d0aac67a639cc68ef660840afe309b807bc9f5"
+
dependencies = [
+
"generic-array",
+
]
[[package]]
name = "ipnet"
···
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
dependencies = [
+
"spin",
+
]
[[package]]
name = "libc"
···
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
+
name = "libm"
+
version = "0.2.8"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058"
+
+
[[package]]
name = "linux-raw-sys"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
+
name = "num-bigint-dig"
+
version = "0.8.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151"
+
dependencies = [
+
"byteorder",
+
"lazy_static",
+
"libm",
+
"num-integer",
+
"num-iter",
+
"num-traits",
+
"rand",
+
"smallvec",
+
"zeroize",
+
]
+
+
[[package]]
+
name = "num-integer"
+
version = "0.1.46"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
+
dependencies = [
+
"num-traits",
+
]
+
+
[[package]]
+
name = "num-iter"
+
version = "0.1.44"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9"
+
dependencies = [
+
"autocfg",
+
"num-integer",
+
"num-traits",
+
]
+
+
[[package]]
+
name = "num-traits"
+
version = "0.2.18"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
+
dependencies = [
+
"autocfg",
+
"libm",
+
]
+
+
[[package]]
name = "num_cpus"
version = "1.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
+
name = "p256"
+
version = "0.13.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
+
dependencies = [
+
"ecdsa",
+
"elliptic-curve",
+
"primeorder",
+
"sha2",
+
]
+
+
[[package]]
+
name = "p384"
+
version = "0.13.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209"
+
dependencies = [
+
"ecdsa",
+
"elliptic-curve",
+
"primeorder",
+
"sha2",
+
]
+
+
[[package]]
+
name = "p521"
+
version = "0.13.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "0fc9e2161f1f215afdfce23677034ae137bbd45016a880c2eb3ba8eb95f085b2"
+
dependencies = [
+
"base16ct",
+
"ecdsa",
+
"elliptic-curve",
+
"primeorder",
+
"rand_core",
+
"sha2",
+
]
+
+
[[package]]
+
name = "pem-rfc7468"
+
version = "0.7.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
+
dependencies = [
+
"base64ct",
+
]
+
+
[[package]]
name = "percent-encoding"
version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
+
name = "pkcs1"
+
version = "0.7.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
+
dependencies = [
+
"der",
+
"pkcs8",
+
"spki",
+
]
+
+
[[package]]
+
name = "pkcs8"
+
version = "0.10.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
+
dependencies = [
+
"der",
+
"spki",
+
]
+
+
[[package]]
name = "pkg-config"
version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2900ede94e305130c13ddd391e0ab7cbaeb783945ae07a279c268cb05109c6cb"
[[package]]
+
name = "ppv-lite86"
+
version = "0.2.17"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
+
+
[[package]]
+
name = "primeorder"
+
version = "0.13.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
+
dependencies = [
+
"elliptic-curve",
+
]
+
+
[[package]]
name = "proc-macro2"
version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
+
name = "rand"
+
version = "0.8.5"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
+
dependencies = [
+
"rand_chacha",
+
"rand_core",
+
]
+
+
[[package]]
+
name = "rand_chacha"
+
version = "0.3.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
+
dependencies = [
+
"ppv-lite86",
+
"rand_core",
+
]
+
+
[[package]]
+
name = "rand_core"
+
version = "0.6.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
+
dependencies = [
+
"getrandom",
+
]
+
+
[[package]]
name = "reqwest"
version = "0.11.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
"wasm-bindgen-futures",
"web-sys",
"winreg",
+
]
+
+
[[package]]
+
name = "rfc6979"
+
version = "0.4.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
+
dependencies = [
+
"hmac",
+
"subtle",
+
]
+
+
[[package]]
+
name = "rsa"
+
version = "0.9.6"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc"
+
dependencies = [
+
"const-oid",
+
"digest",
+
"num-bigint-dig",
+
"num-integer",
+
"num-traits",
+
"pkcs1",
+
"pkcs8",
+
"rand_core",
+
"sha2",
+
"signature",
+
"spki",
+
"subtle",
+
"zeroize",
]
[[package]]
···
]
[[package]]
+
name = "sec1"
+
version = "0.7.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
+
dependencies = [
+
"base16ct",
+
"der",
+
"generic-array",
+
"pkcs8",
+
"subtle",
+
"zeroize",
+
]
+
+
[[package]]
name = "security-framework"
version = "2.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
+
name = "sha2"
+
version = "0.10.8"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8"
+
dependencies = [
+
"cfg-if",
+
"cpufeatures",
+
"digest",
+
]
+
+
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
+
name = "signature"
+
version = "2.2.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
+
dependencies = [
+
"digest",
+
"rand_core",
+
]
+
+
[[package]]
+
name = "simple-eyre"
+
version = "0.3.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "1b561532e8ffe7ecf09108c4f662896a9ec3eac4999eba84015ec3dcb8cc630a"
+
dependencies = [
+
"eyre",
+
"indenter",
+
]
+
+
[[package]]
name = "slab"
version = "0.4.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
+
name = "smallvec"
+
version = "1.13.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
+
+
[[package]]
name = "socket2"
version = "0.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
+
name = "spin"
+
version = "0.5.2"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
+
+
[[package]]
+
name = "spki"
+
version = "0.7.3"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
+
dependencies = [
+
"base64ct",
+
"der",
+
]
+
+
[[package]]
+
name = "ssh-cipher"
+
version = "0.2.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "caac132742f0d33c3af65bfcde7f6aa8f62f0e991d80db99149eb9d44708784f"
+
dependencies = [
+
"cipher",
+
"ssh-encoding",
+
]
+
+
[[package]]
+
name = "ssh-encoding"
+
version = "0.2.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "eb9242b9ef4108a78e8cd1a2c98e193ef372437f8c22be363075233321dd4a15"
+
dependencies = [
+
"base64ct",
+
"pem-rfc7468",
+
"sha2",
+
]
+
+
[[package]]
+
name = "ssh-key"
+
version = "0.6.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "01f8f4ea73476c0aa5d5e6a75ce1e8634e2c3f82005ef3bbed21547ac57f2bf7"
+
dependencies = [
+
"p256",
+
"p384",
+
"p521",
+
"rand_core",
+
"rsa",
+
"sec1",
+
"serde",
+
"sha2",
+
"signature",
+
"ssh-cipher",
+
"ssh-encoding",
+
"subtle",
+
"zeroize",
+
]
+
+
[[package]]
+
name = "strsim"
+
version = "0.10.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
+
+
[[package]]
+
name = "subtle"
+
version = "2.5.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
+
+
[[package]]
name = "syn"
version = "2.0.48"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
]
[[package]]
-
name = "tokio-stream"
-
version = "0.1.14"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
-
dependencies = [
-
"futures-core",
-
"pin-project-lite",
-
"tokio",
-
]
-
-
[[package]]
name = "tokio-util"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
···
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
[[package]]
-
name = "typetag"
-
version = "0.2.15"
-
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "c43148481c7b66502c48f35b8eef38b6ccdc7a9f04bd4cc294226d901ccc9bc7"
-
dependencies = [
-
"erased-serde",
-
"inventory",
-
"once_cell",
-
"serde",
-
"typetag-impl",
-
]
-
-
[[package]]
-
name = "typetag-impl"
-
version = "0.2.15"
+
name = "typenum"
+
version = "1.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-
checksum = "291db8a81af4840c10d636e047cac67664e343be44e24dfdbd1492df9a5d3390"
-
dependencies = [
-
"proc-macro2",
-
"quote",
-
"syn",
-
]
+
checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825"
[[package]]
name = "unicode-bidi"
···
[[package]]
+
name = "utf8parse"
+
version = "0.2.1"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
+
+
[[package]]
name = "vcpkg"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
+
+
[[package]]
+
name = "version_check"
+
version = "0.9.4"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "want"
···
"cfg-if",
"windows-sys 0.48.0",
+
+
[[package]]
+
name = "zeroize"
+
version = "1.7.0"
+
source = "registry+https://github.com/rust-lang/crates.io-index"
+
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"
+3 -4
Cargo.toml
···
version = "0.1.0"
edition = "2021"
-
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
[dependencies]
async-trait = "0.1.77"
+
clap = { version = "4.4.18", features = ["derive"] }
futures = "0.3.30"
reqwest = "0.11.24"
serde = { version = "1.0.196", features = ["derive"] }
serde_json = "1.0.113"
+
simple-eyre = "0.3.1"
+
ssh-key = { version = "0.6.4", features = ["alloc", "serde"] }
tokio = { version = "1.36.0", default-features = false, features = ["rt-multi-thread", "fs", "io-std", "io-util", "macros", "process", "net"] }
-
tokio-stream = "0.1.14"
toml = "0.8.10"
-
typetag = "0.2.15"
+8 -10
README.md
···
## Sources
-
- [ ] Raw - no fetching, just raw key from the configuration
-
- [ ] Forges
-
+ [ ] GitHub
-
+ [ ] SourceHut
-
+ [ ] GitLab
-
+ [ ] Forgejo
-
+ [ ] Defining your own forges
-
- [ ] Host keys via `ssh-keyscan`
+
- [x] Raw - no fetching, just raw key from the configuration
+
- [x] Forges
+
+ [x] GitHub
+
+ [x] SourceHut
+
+ [x] GitLab
+
+ [x] Forgejo
+
- [x] Host keys via `ssh-keyscan`
## Reason
···
```toml
[[entry]]
name = "hauleth"
-
emails = [ "~@hauleth.dev" ]
keys = [
{ sourcehut = "~hauleth" },
{ github = "hauleth" }
···
[[entry]]
name = "heimdall"
keys = [
-
{ host = "heimdall" }
+
{ host = [ "heimdall" ] }
]
```
+17 -5
flake.nix
···
extra-substituters = "https://devenv.cachix.org";
};
-
outputs = inputs@{ flake-parts, ... }:
-
flake-parts.lib.mkFlake { inherit inputs; } {
+
outputs = inputs @ {flake-parts, ...}:
+
flake-parts.lib.mkFlake {inherit inputs;} {
imports = [
inputs.devenv.flakeModule
];
flake = {
-
};
-
systems = [ "x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin" ];
+
systems = ["x86_64-linux" "aarch64-linux" "aarch64-darwin" "x86_64-darwin"];
-
perSystem = { inputs', pkgs, ... }: {
+
perSystem = {
+
self',
+
inputs',
+
pkgs,
+
...
+
}: {
+
formatter = pkgs.alejandra;
+
+
packages = {
+
default = self'.packages.fuk;
+
+
fuk = pkgs.callPackage ./nix/fuk.nix {};
+
};
+
devenv.shells.default = {
languages.rust.enable = true;
+12
keys.toml
···
+
[[entry]]
+
name = "hauleth"
+
keys = [
+
{ sourcehut = "~hauleth" },
+
{ github = "hauleth" }
+
]
+
+
[[entry]]
+
name = "heimdall"
+
keys = [
+
{ hosts = ["heimdall"] }
+
]
+29
nix/fuk.nix
···
+
{
+
lib,
+
rustPlatform,
+
stdenv,
+
darwin,
+
libiconv,
+
}:
+
rustPlatform.buildRustPackage {
+
pname = "fuk";
+
version = "0.1.0";
+
+
src = ./..;
+
+
cargoHash = "sha256-uRCR8SMFurNbgL1ZSLW95tJcZRH3FMYNAc0uWGvH4yw=";
+
+
buildInputs = lib.lists.optionals stdenv.isDarwin (with darwin.apple_sdk; [
+
frameworks.Foundation
+
frameworks.CoreFoundation
+
frameworks.SystemConfiguration
+
frameworks.Security
+
libiconv
+
]);
+
+
meta = with lib; {
+
description = "Simple tool for fetching SSH keys from various sources";
+
homepage = "https://git.sr.ht/~hauleth/fuk";
+
mainProgram = "fuk";
+
};
+
}
+9 -3
src/config.rs
···
#[derive(Debug, serde::Deserialize)]
pub struct Entry {
pub name: String,
-
pub keys: Vec<Box<dyn Fetch>>,
+
pub keys: Vec<Box<Source>>,
}
impl Entry {
-
pub async fn fetch(&self) -> (String, Vec<String>) {
-
let stream = stream::iter(&self.keys)
+
pub async fn fetch(&self) -> (String, Vec<ssh_key::PublicKey>) {
+
let mut stream: Vec<_> = stream::iter(&self.keys)
.then(|k| async { k.fetch().await })
.map(stream::iter)
.flatten()
.collect()
.await;
+
+
// Deduplicate keys, no need for duplicated entries
+
stream.sort();
+
stream.dedup_by(|a, b| {
+
a.key_data() == b.key_data()
+
});
(self.name.clone(), stream)
}
+50 -17
src/main.rs
···
-
const EXAMPLE: &'static str = r#"
-
[[entry]]
-
name = "hauleth"
-
keys = [
-
{ Forge = { user = "~hauleth", host = "meta.sr.ht" } }
-
]
+
use simple_eyre::eyre::Result;
+
use clap::Parser;
+
use std::path::Path;
+
use tokio::fs::File;
+
use tokio::io::{self, AsyncReadExt};
+
+
#[derive(Debug, Clone)]
+
enum Input {
+
File(Box<Path>),
+
Stdio,
+
}
+
+
impl<'a> From<&'a str> for Input {
+
fn from(input: &'a str) -> Self {
+
match input {
+
"-" => Input::Stdio,
+
other => Input::File(Path::new(other).into()),
+
}
+
}
+
}
+
+
impl Input {
+
async fn read_all(&self) -> io::Result<String> {
+
let mut buffer = String::new();
+
let result = match *self {
+
Input::Stdio => io::stdin().read_to_string(&mut buffer).await,
+
Input::File(ref path) => {
+
let mut f = File::open(path).await?;
+
f.read_to_string(&mut buffer).await
+
}
+
};
+
+
result.map(|_| buffer)
+
}
+
}
-
[[entry]]
-
name = "heimdall"
-
keys = [
-
{ Host = [ "heimdall" ] }
-
]
-
"#;
+
#[derive(Debug, Parser)]
+
struct Args {
+
#[arg(long, default_value_t = fuk::output::Format::JSONPretty)]
+
format: fuk::output::Format,
+
/// File containing list of keys to be fetched
+
#[arg(value_hint = clap::ValueHint::FilePath)]
+
file: Input,
+
}
#[tokio::main]
-
async fn main() {
-
let config: fuk::config::Config =
-
toml::from_str(EXAMPLE).unwrap();
+
async fn main() -> Result<()> {
+
let args = Args::parse();
-
println!("{:#?}", config);
+
let config: fuk::config::Config = toml::from_str(&args.file.read_all().await?)?;
let output = fuk::fuk(config).await;
-
println!("{}", serde_json::to_string_pretty(&output.keys).unwrap());
+
+
println!("{}", args.format.render(&output));
+
+
Ok(())
}
+35 -1
src/output/mod.rs
···
use std::collections::HashMap;
+
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
+
pub enum Format {
+
JSON,
+
JSONPretty,
+
}
+
+
impl Format {
+
pub fn render(self, output: &Output) -> String {
+
match self {
+
Format::JSON => serde_json::to_string(&output.keys).unwrap(),
+
Format::JSONPretty => serde_json::to_string_pretty(&output.keys).unwrap(),
+
}
+
}
+
}
+
+
impl std::fmt::Display for Format {
+
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+
match *self {
+
Format::JSON => f.write_str("json"),
+
Format::JSONPretty => f.write_str("pretty"),
+
}
+
}
+
}
+
+
impl<'a> From<&'a str> for Format {
+
fn from(s: &'a str) -> Format {
+
match s {
+
"json" => Format::JSON,
+
"pretty" => Format::JSONPretty,
+
_ => unreachable!()
+
}
+
}
+
}
+
#[derive(Debug, serde::Serialize)]
pub struct Output {
-
pub keys: HashMap<String, Vec<String>>,
+
pub keys: HashMap<String, Vec<ssh_key::PublicKey>>,
}
+38 -13
src/sources/mod.rs
···
+
use ssh_key::PublicKey;
use tokio::process::Command;
-
use serde::Deserialize;
use async_trait::async_trait;
-
#[typetag::deserialize]
#[async_trait]
pub trait Fetch: std::fmt::Debug {
-
async fn fetch(&self) -> Vec<String>;
+
async fn fetch(&self) -> Vec<PublicKey>;
+
}
+
+
#[derive(Debug, Deserialize)]
+
#[serde(rename_all = "lowercase")]
+
pub enum Source {
+
Raw(Raw),
+
Hosts(Hosts),
+
Forge(Forge),
+
Github(String),
+
Sourcehut(String),
+
Gitlab(String),
+
Codeberg(String),
+
}
+
+
#[async_trait]
+
impl Fetch for Source {
+
async fn fetch(&self) -> Vec<PublicKey> {
+
match *self {
+
Source::Raw(ref raw) => raw.fetch().await,
+
Source::Hosts(ref raw) => raw.fetch().await,
+
Source::Forge(ref raw) => raw.fetch().await,
+
Source::Github(ref user) => Forge { user: user.clone(), host: "github.com".into() }.fetch().await,
+
Source::Sourcehut(ref user) => Forge { user: user.clone(), host: "meta.sr.ht".into() }.fetch().await,
+
Source::Gitlab(ref user) => Forge { user: user.clone(), host: "gitlab.com".into() }.fetch().await,
+
Source::Codeberg(ref user) => Forge { user: user.clone(), host: "codeberg.org".into() }.fetch().await,
+
}
+
}
}
#[derive(Debug, Deserialize)]
-
pub struct Raw(Vec<String>);
+
pub struct Raw(Vec<PublicKey>);
-
#[typetag::deserialize]
#[async_trait::async_trait]
impl Fetch for Raw {
-
async fn fetch(&self) -> Vec<String> {
+
async fn fetch(&self) -> Vec<PublicKey> {
self.0.clone()
}
}
#[derive(Debug, Deserialize)]
-
pub struct Host(pub Vec<String>);
+
pub struct Hosts(pub Vec<String>);
-
#[typetag::deserialize]
#[async_trait]
-
impl Fetch for Host {
-
async fn fetch(&self) -> Vec<String> {
+
impl Fetch for Hosts {
+
async fn fetch(&self) -> Vec<PublicKey> {
+
// TODO: Check if we can do it in-process instead of shelling out to `ssh-keyscan`
let result = Command::new("ssh-keyscan")
.args(&self.0)
.output()
···
.join(" ")
.to_owned()
})
+
.map(|k| PublicKey::from_openssh(&k).unwrap())
.collect()
}
}
···
pub host: String,
}
-
#[typetag::deserialize]
#[async_trait]
impl Fetch for Forge {
-
async fn fetch(&self) -> Vec<String> {
+
async fn fetch(&self) -> Vec<PublicKey> {
let url = format!("https://{}/{}.keys", self.host, self.user);
reqwest::get(url)
···
.unwrap()
.trim()
.split('\n')
-
.map(|s| s.to_owned())
+
.map(|s| PublicKey::from_openssh(s).unwrap())
.collect()
}
}