switch to configfile instead of env

This commit is contained in:
Robin Appelman 2024-02-29 23:39:46 +01:00
commit c4d579b033
9 changed files with 629 additions and 274 deletions

2
.gitignore vendored
View file

@ -4,3 +4,5 @@
key* key*
.direnv .direnv
result result
passwordfile
config.toml

514
Cargo.lock generated
View file

@ -17,6 +17,54 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "anstream"
version = "0.6.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
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]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.1.0" version = "1.1.0"
@ -65,12 +113,6 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "bumpalo"
version = "3.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
version = "1.5.0" version = "1.5.0"
@ -98,6 +140,52 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[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]] [[package]]
name = "core-foundation" name = "core-foundation"
version = "0.9.4" version = "0.9.4"
@ -174,6 +262,12 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
[[package]] [[package]]
name = "flume" name = "flume"
version = "0.11.0" version = "0.11.0"
@ -182,7 +276,7 @@ checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181"
dependencies = [ dependencies = [
"futures-core", "futures-core",
"futures-sink", "futures-sink",
"spin 0.9.8", "spin",
] ]
[[package]] [[package]]
@ -281,7 +375,7 @@ dependencies = [
"futures-sink", "futures-sink",
"futures-util", "futures-util",
"http", "http",
"indexmap", "indexmap 1.9.3",
"slab", "slab",
"tokio", "tokio",
"tokio-util", "tokio-util",
@ -294,6 +388,12 @@ version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
[[package]]
name = "hashbrown"
version = "0.14.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604"
[[package]] [[package]]
name = "headers" name = "headers"
version = "0.3.9" version = "0.3.9"
@ -318,6 +418,12 @@ dependencies = [
"http", "http",
] ]
[[package]]
name = "heck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
[[package]] [[package]]
name = "hermit-abi" name = "hermit-abi"
version = "0.3.4" version = "0.3.4"
@ -399,7 +505,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"hashbrown", "hashbrown 0.12.3",
]
[[package]]
name = "indexmap"
version = "2.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4"
dependencies = [
"equivalent",
"hashbrown 0.14.3",
] ]
[[package]] [[package]]
@ -417,15 +533,6 @@ version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "js-sys"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84"
dependencies = [
"wasm-bindgen",
]
[[package]] [[package]]
name = "lazy_static" name = "lazy_static"
version = "1.4.0" version = "1.4.0"
@ -542,7 +649,7 @@ dependencies = [
"log", "log",
"memchr", "memchr",
"mime", "mime",
"spin 0.9.8", "spin",
"version_check", "version_check",
] ]
@ -557,6 +664,16 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "nu-ansi-term"
version = "0.46.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
dependencies = [
"overload",
"winapi",
]
[[package]] [[package]]
name = "num_cpus" name = "num_cpus"
version = "1.16.0" version = "1.16.0"
@ -578,9 +695,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.8.0" version = "1.19.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]] [[package]]
name = "openssl-probe" name = "openssl-probe"
@ -600,6 +717,12 @@ dependencies = [
"vcpkg", "vcpkg",
] ]
[[package]]
name = "overload"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
[[package]] [[package]]
name = "parking_lot" name = "parking_lot"
version = "0.11.2" version = "0.11.2"
@ -648,7 +771,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.48", "syn",
] ]
[[package]] [[package]]
@ -732,21 +855,6 @@ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
] ]
[[package]]
name = "ring"
version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
dependencies = [
"cc",
"libc",
"once_cell",
"spin 0.5.2",
"untrusted 0.7.1",
"web-sys",
"winapi",
]
[[package]] [[package]]
name = "ring" name = "ring"
version = "0.17.7" version = "0.17.7"
@ -756,23 +864,23 @@ dependencies = [
"cc", "cc",
"getrandom", "getrandom",
"libc", "libc",
"spin 0.9.8", "spin",
"untrusted 0.9.0", "untrusted",
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]] [[package]]
name = "rumqttc" name = "rumqttc"
version = "0.23.0" version = "0.24.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8d8941c6791801b667d52bfe9ff4fc7c968d4f3f9ae8ae7abdaaa1c966feafc8" checksum = "e1568e15fab2d546f940ed3a21f48bbbd1c494c90c99c4481339364a497f94a9"
dependencies = [ dependencies = [
"bytes", "bytes",
"flume", "flume",
"futures-util", "futures-util",
"log", "log",
"rustls-native-certs", "rustls-native-certs",
"rustls-pemfile", "rustls-pemfile 2.1.0",
"rustls-webpki", "rustls-webpki",
"thiserror", "thiserror",
"tokio", "tokio",
@ -787,24 +895,27 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]] [[package]]
name = "rustls" name = "rustls"
version = "0.21.10" version = "0.22.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" checksum = "e87c9956bd9807afa1f77e0f7594af32566e830e088a5576d27c5b6f30f49d41"
dependencies = [ dependencies = [
"log", "log",
"ring 0.17.7", "ring",
"rustls-pki-types",
"rustls-webpki", "rustls-webpki",
"sct", "subtle",
"zeroize",
] ]
[[package]] [[package]]
name = "rustls-native-certs" name = "rustls-native-certs"
version = "0.6.3" version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9aace74cb666635c918e9c12bc0d348266037aa8eb599b5cba565709a8dff00" checksum = "8f1fb85efa936c42c6d5fc28d2629bb51e4b2f4b8a5211e297d599cc5a093792"
dependencies = [ dependencies = [
"openssl-probe", "openssl-probe",
"rustls-pemfile", "rustls-pemfile 2.1.0",
"rustls-pki-types",
"schannel", "schannel",
"security-framework", "security-framework",
] ]
@ -819,13 +930,30 @@ dependencies = [
] ]
[[package]] [[package]]
name = "rustls-webpki" name = "rustls-pemfile"
version = "0.101.7" version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" checksum = "3c333bb734fcdedcea57de1602543590f545f127dc8b533324318fd492c5c70b"
dependencies = [ dependencies = [
"ring 0.17.7", "base64",
"untrusted 0.9.0", "rustls-pki-types",
]
[[package]]
name = "rustls-pki-types"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ede67b28608b4c60685c7d54122d4400d90f62b40caee7700e700380a390fa8"
[[package]]
name = "rustls-webpki"
version = "0.102.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "faaa0a62740bedb9b2ef5afa303da42764c012f743917351dc9a237ea1663610"
dependencies = [
"ring",
"rustls-pki-types",
"untrusted",
] ]
[[package]] [[package]]
@ -856,13 +984,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]] [[package]]
name = "sct" name = "secretfile"
version = "0.7.0" version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" checksum = "746c54b939ab8d393b536765393c0bd7634fca94eed62321ec3e3559293f6c21"
dependencies = [ dependencies = [
"ring 0.16.20", "thiserror",
"untrusted 0.7.1",
] ]
[[package]] [[package]]
@ -890,22 +1017,22 @@ dependencies = [
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.196" version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32" checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.196" version = "1.0.197"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67" checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.48", "syn",
] ]
[[package]] [[package]]
@ -919,6 +1046,15 @@ dependencies = [
"serde", "serde",
] ]
[[package]]
name = "serde_spanned"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "serde_urlencoded" name = "serde_urlencoded"
version = "0.7.1" version = "0.7.1"
@ -942,6 +1078,15 @@ dependencies = [
"digest", "digest",
] ]
[[package]]
name = "sharded-slab"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
dependencies = [
"lazy_static",
]
[[package]] [[package]]
name = "slab" name = "slab"
version = "0.4.9" version = "0.4.9"
@ -967,12 +1112,6 @@ dependencies = [
"windows-sys 0.48.0", "windows-sys 0.48.0",
] ]
[[package]]
name = "spin"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]] [[package]]
name = "spin" name = "spin"
version = "0.9.8" version = "0.9.8"
@ -995,15 +1134,16 @@ dependencies = [
] ]
[[package]] [[package]]
name = "syn" name = "strsim"
version = "1.0.109" version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
dependencies = [
"proc-macro2", [[package]]
"quote", name = "subtle"
"unicode-ident", version = "2.5.0"
] source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc"
[[package]] [[package]]
name = "syn" name = "syn"
@ -1018,22 +1158,32 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.56" version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.56" version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.48", "syn",
]
[[package]]
name = "thread_local"
version = "1.1.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
dependencies = [
"cfg-if",
"once_cell",
] ]
[[package]] [[package]]
@ -1076,16 +1226,17 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.48", "syn",
] ]
[[package]] [[package]]
name = "tokio-rustls" name = "tokio-rustls"
version = "0.24.1" version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f"
dependencies = [ dependencies = [
"rustls", "rustls",
"rustls-pki-types",
"tokio", "tokio",
] ]
@ -1126,6 +1277,40 @@ dependencies = [
"tracing", "tracing",
] ]
[[package]]
name = "toml"
version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290"
dependencies = [
"serde",
"serde_spanned",
"toml_datetime",
"toml_edit",
]
[[package]]
name = "toml_datetime"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1"
dependencies = [
"serde",
]
[[package]]
name = "toml_edit"
version = "0.22.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6"
dependencies = [
"indexmap 2.2.5",
"serde",
"serde_spanned",
"toml_datetime",
"winnow",
]
[[package]] [[package]]
name = "tower-service" name = "tower-service"
version = "0.3.2" version = "0.3.2"
@ -1134,23 +1319,60 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]] [[package]]
name = "tracing" name = "tracing"
version = "0.1.34" version = "0.1.40"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
dependencies = [ dependencies = [
"cfg-if",
"log", "log",
"pin-project-lite", "pin-project-lite",
"tracing-attributes",
"tracing-core", "tracing-core",
] ]
[[package]] [[package]]
name = "tracing-core" name = "tracing-attributes"
version = "0.1.26" version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
dependencies = [ dependencies = [
"lazy_static", "proc-macro2",
"quote",
"syn",
]
[[package]]
name = "tracing-core"
version = "0.1.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
dependencies = [
"once_cell",
"valuable",
]
[[package]]
name = "tracing-log"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
dependencies = [
"log",
"once_cell",
"tracing-core",
]
[[package]]
name = "tracing-subscriber"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
dependencies = [
"nu-ansi-term",
"sharded-slab",
"smallvec",
"thread_local",
"tracing-core",
"tracing-log",
] ]
[[package]] [[package]]
@ -1214,12 +1436,6 @@ dependencies = [
"tinyvec", "tinyvec",
] ]
[[package]]
name = "untrusted"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
[[package]] [[package]]
name = "untrusted" name = "untrusted"
version = "0.9.0" version = "0.9.0"
@ -1243,6 +1459,18 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "utf8parse"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]]
name = "valuable"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
[[package]] [[package]]
name = "vcpkg" name = "vcpkg"
version = "0.2.15" version = "0.2.15"
@ -1282,7 +1510,7 @@ dependencies = [
"multer", "multer",
"percent-encoding", "percent-encoding",
"pin-project", "pin-project",
"rustls-pemfile", "rustls-pemfile 1.0.4",
"scoped-tls", "scoped-tls",
"serde", "serde",
"serde_json", "serde_json",
@ -1301,80 +1529,23 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b"
dependencies = [
"bumpalo",
"lazy_static",
"log",
"proc-macro2",
"quote",
"syn 1.0.109",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc"
[[package]]
name = "web-sys"
version = "0.3.55"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb"
dependencies = [
"js-sys",
"wasm-bindgen",
]
[[package]] [[package]]
name = "wifi-prometheus-exporter" name = "wifi-prometheus-exporter"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"clap",
"ctrlc", "ctrlc",
"dotenvy", "dotenvy",
"main_error", "main_error",
"rumqttc", "rumqttc",
"secretfile",
"serde",
"ssh2", "ssh2",
"thiserror",
"tokio", "tokio",
"toml",
"tracing",
"tracing-subscriber",
"warp", "warp",
] ]
@ -1531,3 +1702,18 @@ name = "windows_x86_64_msvc"
version = "0.52.0" version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
[[package]]
name = "winnow"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8"
dependencies = [
"memchr",
]
[[package]]
name = "zeroize"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525b4ec142c6b68a2d10f01f7bbf6755599ca3f81ea53b8431b7dd348f5fdb2d"

View file

@ -3,8 +3,7 @@ name = "wifi-prometheus-exporter"
version = "0.1.0" version = "0.1.0"
authors = ["Robin Appelman <robin@icewind.nl>"] authors = ["Robin Appelman <robin@icewind.nl>"]
edition = "2018" edition = "2018"
license = "MIT OR Apache-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
ssh2 = "0.9.4" ssh2 = "0.9.4"
@ -13,4 +12,11 @@ main_error = "0.1.2"
tokio = { version = "1.36.0", features = ["macros", "rt-multi-thread"] } tokio = { version = "1.36.0", features = ["macros", "rt-multi-thread"] }
warp = "0.3.6" warp = "0.3.6"
ctrlc = "3.4.2" ctrlc = "3.4.2"
rumqttc = "0.23.0" thiserror = "1.0.57"
rumqttc = "0.24.0"
serde = { version = "1.0.197", features = ["derive"] }
toml = "0.8.10"
secretfile = { version = "0.1.0" }
clap = { version = "=4.4.18", features = ["derive"] }
tracing = "0.1.40"
tracing-subscriber = "0.3.18"

13
config.sample.toml Normal file
View file

@ -0,0 +1,13 @@
[mqtt]
hostname = "mqtt.example.com"
username = "wifi-exporter"
password_file = "/path/to/password"
[exporter]
port = 1234
interfaces = ["eth1", "eth2"]
[ssh]
host = "accesspoint.example.com:22"
key_file = "/path/to/ssh/key"
pubkey_file = "/path/to/ssh/key.pub"

View file

@ -6,23 +6,67 @@
}: }:
with lib; let with lib; let
cfg = config.services.wifi-prometheus-exporter; cfg = config.services.wifi-prometheus-exporter;
format = pkgs.formats.toml {};
configFile = format.generate "wifi-prometheus-exporter-config.toml" {
ssh = {
inherit (cfg.ssh) address;
key_file = "$CREDENTIALS_DIRECTORY/ssh_key";
pubkey_file = "$CREDENTIALS_DIRECTORY/ssh_pub_key";
};
exporter = {
inherit (cfg) interfaces port;
};
mqtt = {
inherit (cfg.mqtt) hostname port username;
password_file = "$CREDENTIALS_DIRECTORY/mqtt_password";
};
};
in { in {
options.services.wifi-prometheus-exporter = { options.services.wifi-prometheus-exporter = {
enable = mkEnableOption "WiFi prometheus exporter"; enable = mkEnableOption "WiFi prometheus exporter";
sshAddress = mkOption { ssh = mkOption {
type = types.submodule {
options = {
address = mkOption {
type = types.str; type = types.str;
description = "ssh address of the wifi access point"; description = "ssh address of the access point";
};
keyFile = mkOption {
type = types.str;
description = "path to ssh key file";
};
pubKeyFile = mkOption {
type = types.str;
description = "path to ssh public key";
};
};
};
}; };
sshKeyFile = mkOption { mqtt = mkOption {
type = types.submodule {
options = {
hostname = mkOption {
type = types.str; type = types.str;
description = "path containing the ssh private key"; description = "mqtt server hostname";
}; };
port = mkOption {
sshPubKeyFile = mkOption { type = types.port;
description = "mqtt server port";
default = 1883;
};
username = mkOption {
type = types.str; type = types.str;
description = "path containing the ssh public key"; description = "mqtt username";
};
passwordFile = mkOption {
type = types.str;
description = "path containing the mqtt password";
};
};
};
}; };
interfaces = mkOption { interfaces = mkOption {
@ -36,32 +80,33 @@ in {
description = "port to listen to"; description = "port to listen to";
}; };
mqttSecretFile = mkOption {
type = types.str;
description = "path containing MQTT_HOSTNAME, MQTT_USERNAME and MQTT_PASSWORD environment variables";
};
package = mkOption { package = mkOption {
type = types.package; type = types.package;
defaultText = literalExpression "pkgs.dispenser"; defaultText = literalExpression "pkgs.dispenser";
description = "package to use"; description = "package to use";
}; };
log = mkOption {
type = types.str;
description = "log level";
default = "info";
};
}; };
config = mkIf cfg.enable { config = mkIf cfg.enable {
systemd.services."wifi-prometheus-exporter" = { systemd.services."wifi-prometheus-exporter" = {
wantedBy = ["multi-user.target"]; wantedBy = ["multi-user.target"];
environment = { environment = {
PORT = toString cfg.port; RUST_LOG = cfg.log;
ADDR = cfg.sshAddress;
KEYFILE = cfg.sshKeyFile;
PUBFILE = cfg.sshPubKeyFile;
INTERFACES = concatStringsSep " " cfg.interfaces;
}; };
serviceConfig = { serviceConfig = {
ExecStart = "${pkgs.wifi-prometheus-exporter}/bin/wifi-prometheus-exporter"; ExecStart = "${pkgs.wifi-prometheus-exporter}/bin/wifi-prometheus-exporter ${configFile}";
EnvironmentFile = cfg.mqttSecretFile; LoadCredential = [
"ssh_key:${cfg.ssh.keyFile}"
"ssh_pub_key:${cfg.ssh.pubKeyFile}"
"mqtt_password:${cfg.mqtt.passwordFile}"
];
Restart = "on-failure"; Restart = "on-failure";
DynamicUser = true; DynamicUser = true;
PrivateTmp = true; PrivateTmp = true;

68
src/config.rs Normal file
View file

@ -0,0 +1,68 @@
use crate::error::Error;
use secretfile::load;
use serde::Deserialize;
use std::fs::read_to_string;
use std::net::{IpAddr, Ipv4Addr};
use std::path::Path;
#[derive(Debug, Deserialize)]
pub struct Config {
pub mqtt: Option<MqttConfig>,
pub ssh: SshConfig,
pub exporter: ExporterConfig,
}
impl Config {
pub fn load(path: &Path) -> Result<Self, Error> {
let content = read_to_string(path).map_err(Error::ReadConfig)?;
toml::from_str(&content).map_err(Error::ParseConfig)
}
}
#[derive(Debug, Deserialize)]
pub struct MqttConfig {
pub hostname: String,
#[serde(default = "default_mqtt_port")]
pub port: u16,
pub username: String,
password_file: String,
}
fn default_mqtt_port() -> u16 {
1883
}
impl MqttConfig {
pub fn password(&self) -> Result<String, Error> {
Ok(load(&self.password_file)?)
}
}
#[derive(Debug, Deserialize)]
pub struct SshConfig {
pub address: String,
pubkey_file: String,
key_file: String,
}
impl SshConfig {
pub fn key(&self) -> Result<String, Error> {
Ok(load(&self.key_file)?)
}
pub fn pubkey(&self) -> Result<String, Error> {
Ok(load(&self.pubkey_file)?)
}
}
#[derive(Debug, Deserialize)]
pub struct ExporterConfig {
#[serde(default = "default_address")]
pub address: IpAddr,
pub port: u16,
pub interfaces: Vec<String>,
}
fn default_address() -> IpAddr {
Ipv4Addr::new(127, 0, 0, 1).into()
}

18
src/error.rs Normal file
View file

@ -0,0 +1,18 @@
use secretfile::SecretError;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum Error {
#[error("failed to read config: {0}")]
ReadConfig(std::io::Error),
#[error("failed to parse config: {0}")]
ParseConfig(toml::de::Error),
#[error("failed to secret: {0:#}")]
Secret(#[from] SecretError),
#[error("failed to connect to ssh server: {0}")]
SshConnect(std::io::Error),
#[error("failed to start ssh session: {0}")]
SshSession(ssh2::Error),
#[error("failed to authenticate ssh session: {0}")]
SshAuth(ssh2::Error),
}

61
src/listener.rs Normal file
View file

@ -0,0 +1,61 @@
use crate::error::Error;
use ssh2::{ErrorCode, Session};
use std::fmt::Debug;
use std::io::Read;
use std::net::{TcpStream, ToSocketAddrs};
use tracing::{debug, info};
pub struct WifiLister {
command: String,
session: Session,
}
impl WifiLister {
pub fn new<A: ToSocketAddrs + Debug>(
addr: A,
key: &str,
pubkey: &str,
interfaces: &[String],
) -> Result<Self, Error> {
debug!(address = ?addr, "connecting to ssh");
let tcp = TcpStream::connect(&addr).map_err(Error::SshConnect)?;
let mut session = Session::new().map_err(Error::SshSession)?;
session.set_tcp_stream(tcp);
session.handshake().map_err(Error::SshSession)?;
session
.userauth_pubkey_memory("admin", Some(pubkey), key, None)
.map_err(Error::SshAuth)?;
let command = if interfaces.is_empty() {
"wl assoclist".to_string()
} else {
let commands: Vec<String> = interfaces
.iter()
.map(|interface| format!("wl -a {} assoclist", interface))
.collect();
commands.join(" && ")
};
info!("ssh connected");
Ok(WifiLister { session, command })
}
pub fn list_connected_devices(&self) -> Result<Vec<String>, ssh2::Error> {
let mut channel = self.session.channel_session()?;
debug!(command = self.command, "sending ssh command");
channel.exec(&self.command)?;
let mut s = String::new();
channel.read_to_string(&mut s).map_err(|e| {
ssh2::Error::new(
ErrorCode::Session(e.raw_os_error().unwrap_or_default()),
"error reading from ssh stream",
)
})?;
channel.wait_close()?;
Ok(s.lines()
.map(|s| s.trim_start_matches("assoclist ").to_string())
.collect())
}
}

View file

@ -1,109 +1,63 @@
mod config;
mod error;
mod listener;
use crate::config::Config;
use crate::listener::WifiLister;
use clap::Parser;
use main_error::MainError; use main_error::MainError;
use rumqttc::{AsyncClient, ClientError, MqttOptions, QoS}; use rumqttc::{AsyncClient, ClientError, MqttOptions, QoS};
use ssh2::{ErrorCode, Session};
use std::collections::HashMap; use std::collections::HashMap;
use std::ffi::OsStr;
use std::fmt::{Display, Formatter, Write}; use std::fmt::{Display, Formatter, Write};
use std::io::prelude::*; use std::path::PathBuf;
use std::net::{TcpStream, ToSocketAddrs};
use std::path::Path;
use std::str::FromStr;
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use std::time::Duration; use std::time::Duration;
use tokio::{spawn, time::sleep}; use tokio::{spawn, time::sleep};
use tracing::{error, info};
use warp::Filter; use warp::Filter;
struct WifiLister { #[derive(Parser, Debug)]
command: String, struct Args {
session: Session, /// Path to config file
} config: PathBuf,
impl WifiLister {
pub fn new<A: ToSocketAddrs, Priv: AsRef<OsStr>, Pub: AsRef<OsStr>>(
addr: A,
keyfile: Priv,
pubkey: Pub,
interfaces: &[&str],
) -> Result<Self, MainError> {
let tcp = TcpStream::connect(addr)?;
let mut session = Session::new()?;
session.set_tcp_stream(tcp);
session.handshake()?;
let keyfile = Path::new(keyfile.as_ref());
let pubkey = Path::new(pubkey.as_ref());
session.userauth_pubkey_file("admin", Some(pubkey), keyfile, None)?;
let command = if interfaces.is_empty() {
"wl assoclist".to_string()
} else {
let commands: Vec<String> = interfaces
.iter()
.map(|interface| format!("wl -a {} assoclist", interface))
.collect();
commands.join(" && ")
};
Ok(WifiLister { session, command })
}
pub fn list_connected_devices(&self) -> Result<Vec<String>, ssh2::Error> {
let mut channel = self.session.channel_session()?;
channel.exec(&self.command)?;
let mut s = String::new();
channel.read_to_string(&mut s).map_err(|e| {
ssh2::Error::new(
ErrorCode::Session(e.raw_os_error().unwrap_or_default()),
"error reading from ssh stream",
)
})?;
channel.wait_close()?;
Ok(s.lines()
.map(|s| s.trim_start_matches("assoclist ").to_string())
.collect())
}
} }
#[tokio::main] #[tokio::main]
async fn main() -> Result<(), MainError> { async fn main() -> Result<(), MainError> {
let mut env: HashMap<String, String> = dotenvy::vars().collect(); tracing_subscriber::fmt::init();
let addr = env.remove("ADDR").ok_or("No ADDR set")?; let args = Args::parse();
let keyfile = env.remove("KEYFILE").ok_or("No KEYFILE set")?; let config = Config::load(&args.config)?;
let pubfile = env.remove("PUBFILE").ok_or("No PUBFILE set")?; let mqtt_options = match &config.mqtt {
let port = env Some(mqtt_config) => {
.get("PORT") let mut mqtt_options =
.and_then(|s| u16::from_str(s).ok()) MqttOptions::new("wifi-exporter", &mqtt_config.hostname, mqtt_config.port);
.unwrap_or(80);
let mqtt_host = env.remove("MQTT_HOSTNAME");
let mqtt_user = env.remove("MQTT_USERNAME");
let mqtt_pass = env.remove("MQTT_PASSWORD");
let interfaces: Vec<&str> = env
.get("INTERFACES")
.map(|interfaces| interfaces.split(' ').collect())
.unwrap_or_default();
let mqtt_options = match (mqtt_host, mqtt_user, mqtt_pass) {
(Some(host), Some(user), Some(pass)) => {
let mut mqtt_options = MqttOptions::new("wifi-exporter", host, 1883);
mqtt_options.set_keep_alive(Duration::from_secs(5)); mqtt_options.set_keep_alive(Duration::from_secs(5));
mqtt_options.set_credentials(user, pass); mqtt_options.set_credentials(&mqtt_config.username, mqtt_config.password()?);
println!("mqtt enabled"); info!("mqtt enabled");
Some(mqtt_options) Some(mqtt_options)
} }
_ => { _ => {
println!("mqtt disabled"); info!("mqtt disabled");
None None
} }
}; };
if interfaces.is_empty() { if config.exporter.interfaces.is_empty() {
println!("Listening on default interface"); info!("Listening on default interface");
} else { } else {
println!("Listening on interfaces: {}", interfaces.join(", ")); info!(
"Listening on interfaces: {}",
config.exporter.interfaces.join(", ")
);
} }
let connected: Arc<Mutex<DeviceStates>> = Default::default(); let connected: Arc<Mutex<DeviceStates>> = Default::default();
let wifi_listener = WifiLister::new(addr, &keyfile, &pubfile, &interfaces)?; let wifi_listener = WifiLister::new(
&config.ssh.address,
&config.ssh.key()?,
&config.ssh.pubkey()?,
&config.exporter.interfaces,
)?;
spawn(listener(wifi_listener, connected.clone(), mqtt_options)); spawn(listener(wifi_listener, connected.clone(), mqtt_options));
@ -114,7 +68,9 @@ async fn main() -> Result<(), MainError> {
}) })
.expect("Error setting Ctrl-C handler"); .expect("Error setting Ctrl-C handler");
warp::serve(metrics).run(([0, 0, 0, 0], port)).await; warp::serve(metrics)
.run((config.exporter.address, config.exporter.port))
.await;
Ok(()) Ok(())
} }
@ -207,15 +163,15 @@ async fn listener(
Ok(devices) => { Ok(devices) => {
let updates = connected.lock().unwrap().update(devices); let updates = connected.lock().unwrap().update(devices);
for (mac, update) in updates { for (mac, update) in updates {
println!("{} {}", mac, update); info!(mac, %update, "change detected");
if let Some(client) = client.as_mut() { if let Some(client) = client.as_mut() {
if let Err(e) = send_update(client, mac, update).await { if let Err(e) = send_update(client, mac, update).await {
eprintln!("Error while sending mqtt update: {:?}", e); error!(e = ?e, "Error while sending mqtt update: {e}");
} }
} }
} }
} }
Err(e) => eprintln!("Error while listing devices {:#?}", e), Err(e) => error!(e = ?e, "Error while listing devices {e}"),
} }
sleep(Duration::from_secs(5)).await; sleep(Duration::from_secs(5)).await;
} }