difftreelog
feat move secret generation helpers to core
in: trunk
13 files changed
Cargo.lockdiffbeforeafterboth--- a/Cargo.lock
+++ b/Cargo.lock
@@ -38,9 +38,9 @@
[[package]]
name = "aes"
-version = "0.8.3"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac1f845298e95f983ff1944b728ae08b8cebab80d684f0a832ed0fc74dfa27e2"
+checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
dependencies = [
"cfg-if",
"cipher",
@@ -63,14 +63,14 @@
[[package]]
name = "age"
-version = "0.9.2"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6d55a4d912c80a92762ffd1c884065f3f9646467d22c95390e824a0ff7def472"
+checksum = "edeef7d7b199195a2d7d7a8155d2d04aee736e60c5c7bdd7097d115369a8817d"
dependencies = [
"aes",
"aes-gcm",
"age-core",
- "base64 0.13.1",
+ "base64",
"bcrypt-pbkdf",
"bech32",
"cbc",
@@ -79,7 +79,6 @@
"cookie-factory",
"ctr",
"curve25519-dalek",
- "hkdf",
"hmac",
"i18n-embed",
"i18n-embed-fl",
@@ -87,8 +86,7 @@
"nom",
"num-traits",
"pin-project",
- "rand 0.7.3",
- "rand 0.8.5",
+ "rand",
"rsa",
"rust-embed",
"scrypt",
@@ -100,17 +98,17 @@
[[package]]
name = "age-core"
-version = "0.9.0"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3d2e815ac879dc23c1139e720d21c6cd4d1276345c772587285d965a69b8f32"
+checksum = "a5f11899bc2bbddd135edbc30c36b1924fa59d0746bb45beb5933fafe3fe509b"
dependencies = [
- "base64 0.13.1",
+ "base64",
"chacha20poly1305",
"cookie-factory",
"hkdf",
"io_tee",
"nom",
- "rand 0.8.5",
+ "rand",
"secrecy",
"sha2",
]
@@ -150,29 +148,10 @@
]
[[package]]
-name = "ansi-str"
-version = "0.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cf4578926a981ab0ca955dc023541d19de37112bc24c1a197bd806d3d86ad1d"
-dependencies = [
- "ansitok",
-]
-
-[[package]]
-name = "ansitok"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "220044e6a1bb31ddee4e3db724d29767f352de47445a6cd75e1a173142136c83"
-dependencies = [
- "nom",
- "vte 0.10.1",
-]
-
-[[package]]
name = "anstream"
-version = "0.6.5"
+version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6"
+checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -184,9 +163,9 @@
[[package]]
name = "anstyle"
-version = "1.0.4"
+version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
+checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
[[package]]
name = "anstyle-parse"
@@ -218,9 +197,9 @@
[[package]]
name = "anyhow"
-version = "1.0.77"
+version = "1.0.79"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c9d19de80eff169429ac1e9f48fffb163916b448a44e8e046186232046d9e1f9"
+checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
[[package]]
name = "arc-swap"
@@ -230,12 +209,6 @@
[[package]]
name = "arrayvec"
-version = "0.5.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
-
-[[package]]
-name = "arrayvec"
version = "0.7.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711"
@@ -248,18 +221,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.48",
-]
-
-[[package]]
-name = "atty"
-version = "0.2.14"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
-dependencies = [
- "hermit-abi 0.1.19",
- "libc",
- "winapi",
+ "syn 2.0.49",
]
[[package]]
@@ -285,15 +247,9 @@
[[package]]
name = "base64"
-version = "0.13.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
-
-[[package]]
-name = "base64"
-version = "0.21.5"
+version = "0.21.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9"
+checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567"
[[package]]
name = "base64ct"
@@ -303,9 +259,9 @@
[[package]]
name = "bcrypt-pbkdf"
-version = "0.9.0"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3806a8db60cf56efee531616a34a6aaa9a114d6da2add861b0fa4a188881b2c7"
+checksum = "6aeac2e1fe888769f34f05ac343bbef98b14d1ffb292ab69d4608b3abc86f2a2"
dependencies = [
"blowfish",
"pbkdf2",
@@ -338,9 +294,9 @@
[[package]]
name = "bitflags"
-version = "2.4.1"
+version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
+checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf"
dependencies = [
"serde",
]
@@ -375,9 +331,9 @@
[[package]]
name = "bumpalo"
-version = "3.14.0"
+version = "3.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
+checksum = "d32a994c2b3ca201d9b263612a374263f05e7adde37c4707f693dcd375076d1f"
[[package]]
name = "bytecount"
@@ -456,9 +412,9 @@
[[package]]
name = "chrono"
-version = "0.4.31"
+version = "0.4.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38"
+checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b"
dependencies = [
"android-tzdata",
"iana-time-zone",
@@ -466,7 +422,7 @@
"num-traits",
"serde",
"wasm-bindgen",
- "windows-targets 0.48.5",
+ "windows-targets 0.52.0",
]
[[package]]
@@ -482,9 +438,9 @@
[[package]]
name = "clap"
-version = "4.4.12"
+version = "4.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcfab8ba68f3668e89f6ff60f5b205cea56aa7b769451a59f34b8682f51c056d"
+checksum = "c918d541ef2913577a0f9566e9ce27cb35b6df072075769e0b26cb5a554520da"
dependencies = [
"clap_builder",
"clap_derive",
@@ -492,14 +448,14 @@
[[package]]
name = "clap_builder"
-version = "4.4.12"
+version = "4.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9"
+checksum = "9f3e7391dad68afb0c2ede1bf619f579a3dc9c2ec67f089baa397123a2f3d1eb"
dependencies = [
"anstream",
"anstyle",
"clap_lex",
- "strsim",
+ "strsim 0.11.0",
"terminal_size",
"unicase",
"unicode-width",
@@ -507,21 +463,21 @@
[[package]]
name = "clap_derive"
-version = "4.4.7"
+version = "4.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
+checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47"
dependencies = [
"heck",
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.49",
]
[[package]]
name = "clap_lex"
-version = "0.6.0"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
+checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
[[package]]
name = "colorchoice"
@@ -531,15 +487,15 @@
[[package]]
name = "console"
-version = "0.15.7"
+version = "0.15.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8"
+checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb"
dependencies = [
"encode_unicode",
"lazy_static",
"libc",
"unicode-width",
- "windows-sys 0.45.0",
+ "windows-sys 0.52.0",
]
[[package]]
@@ -568,9 +524,9 @@
[[package]]
name = "cpufeatures"
-version = "0.2.11"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ce420fe07aecd3e67c5f910618fe65e94158f6dcc0adf44e00d69ce2bdfe0fd0"
+checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504"
dependencies = [
"libc",
]
@@ -582,7 +538,7 @@
checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
dependencies = [
"generic-array",
- "rand_core 0.6.4",
+ "rand_core",
"typenum",
]
@@ -597,18 +553,32 @@
[[package]]
name = "curve25519-dalek"
-version = "3.2.0"
+version = "4.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b9fdf9972b2bd6af2d913799d9ebc165ea4d2e65878e329d9c6b372c4491b61"
+checksum = "0a677b8922c94e01bdbb12126b0bc852f00447528dee1782229af9c720c3f348"
dependencies = [
- "byteorder",
- "digest 0.9.0",
- "rand_core 0.5.1",
+ "cfg-if",
+ "cpufeatures",
+ "curve25519-dalek-derive",
+ "fiat-crypto",
+ "platforms",
+ "rustc_version",
"subtle",
"zeroize",
]
[[package]]
+name = "curve25519-dalek-derive"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.49",
+]
+
+[[package]]
name = "dashmap"
version = "5.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -623,9 +593,9 @@
[[package]]
name = "der"
-version = "0.6.1"
+version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1a467a65c5e759bce6e65eaf91cc29f466cdc57cb65777bd646872a8a1fd4de"
+checksum = "fffa369a668c8af7dbf8b5e56c9f744fbd399949ed171606040001947de40b1c"
dependencies = [
"const-oid",
"zeroize",
@@ -639,15 +609,6 @@
dependencies = [
"powerfmt",
"serde",
-]
-
-[[package]]
-name = "digest"
-version = "0.9.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066"
-dependencies = [
- "generic-array",
]
[[package]]
@@ -660,27 +621,6 @@
"const-oid",
"crypto-common",
"subtle",
-]
-
-[[package]]
-name = "dirs"
-version = "5.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225"
-dependencies = [
- "dirs-sys",
-]
-
-[[package]]
-name = "dirs-sys"
-version = "0.4.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c"
-dependencies = [
- "libc",
- "option-ext",
- "redox_users",
- "windows-sys 0.48.0",
]
[[package]]
@@ -691,14 +631,14 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.49",
]
[[package]]
name = "either"
-version = "1.9.0"
+version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
+checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
[[package]]
name = "encode_unicode"
@@ -707,19 +647,6 @@
checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f"
[[package]]
-name = "env_logger"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece"
-dependencies = [
- "humantime",
- "is-terminal",
- "log",
- "regex",
- "termcolor",
-]
-
-[[package]]
name = "equivalent"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -742,6 +669,12 @@
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
[[package]]
+name = "fiat-crypto"
+version = "0.2.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1676f435fc1dadde4d03e43f5d62b259e1ce5f40bd4ffb21db2b42ebe59c1382"
+
+[[package]]
name = "find-crate"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -759,7 +692,7 @@
"age-core",
"anyhow",
"async-trait",
- "base64 0.21.5",
+ "base64",
"better-command",
"chrono",
"clap",
@@ -797,12 +730,12 @@
"age",
"anyhow",
"clap",
- "env_logger",
- "log",
"nix",
"serde",
"serde_json",
"tempfile",
+ "tracing",
+ "tracing-subscriber",
"z85",
]
@@ -912,7 +845,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.49",
]
[[package]]
@@ -957,24 +890,13 @@
[[package]]
name = "getrandom"
-version = "0.1.16"
+version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
+checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5"
dependencies = [
"cfg-if",
"libc",
- "wasi 0.9.0+wasi-snapshot-preview1",
-]
-
-[[package]]
-name = "getrandom"
-version = "0.2.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasi",
]
[[package]]
@@ -1013,20 +935,11 @@
[[package]]
name = "hermit-abi"
-version = "0.1.19"
+version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
-dependencies = [
- "libc",
-]
+checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd"
[[package]]
-name = "hermit-abi"
-version = "0.3.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
-
-[[package]]
name = "hkdf"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1041,7 +954,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
dependencies = [
- "digest 0.10.7",
+ "digest",
]
[[package]]
@@ -1062,12 +975,6 @@
checksum = "f58b778a5761513caf593693f8951c97a5b610841e754788400f32102eefdff1"
[[package]]
-name = "humantime"
-version = "2.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
-
-[[package]]
name = "i18n-config"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1077,15 +984,15 @@
"serde",
"serde_derive",
"thiserror",
- "toml 0.8.8",
+ "toml 0.8.10",
"unic-langid",
]
[[package]]
name = "i18n-embed"
-version = "0.13.9"
+version = "0.14.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92a86226a7a16632de6723449ee5fe70bac5af718bc642ee9ca2f0f6e14fa1fa"
+checksum = "94205d95764f5bb9db9ea98fa77f89653365ca748e27161f5bbea2ffd50e459c"
dependencies = [
"arc-swap",
"fluent",
@@ -1104,9 +1011,9 @@
[[package]]
name = "i18n-embed-fl"
-version = "0.6.7"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d26a3d3569737dfaac7fc1c4078e6af07471c3060b8e570bcd83cdd5f4685395"
+checksum = "9fc1f8715195dffc4caddcf1cf3128da15fe5d8a137606ea8856c9300047d5a2"
dependencies = [
"dashmap",
"find-crate",
@@ -1118,8 +1025,8 @@
"proc-macro-error",
"proc-macro2",
"quote",
- "strsim",
- "syn 2.0.48",
+ "strsim 0.10.0",
+ "syn 2.0.49",
"unic-langid",
]
@@ -1133,14 +1040,14 @@
"i18n-config",
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.49",
]
[[package]]
name = "iana-time-zone"
-version = "0.1.59"
+version = "0.1.60"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b6a67363e2aa4443928ce15e57ebae94fd8949958fd1223c4cfc0cd473ad7539"
+checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141"
dependencies = [
"android_system_properties",
"core-foundation-sys",
@@ -1161,9 +1068,9 @@
[[package]]
name = "indexmap"
-version = "2.1.0"
+version = "2.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
+checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177"
dependencies = [
"equivalent",
"hashbrown 0.14.3",
@@ -1171,9 +1078,9 @@
[[package]]
name = "indicatif"
-version = "0.17.7"
+version = "0.17.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb28741c9db9a713d93deb3bb9515c20788cef5815265bee4980e87bde7e0f25"
+checksum = "763a5a8f45087d6bcea4222e7b72c291a054edf80e4ef6efd2a4979878c7bea3"
dependencies = [
"console",
"instant",
@@ -1229,26 +1136,26 @@
[[package]]
name = "is-terminal"
-version = "0.4.10"
+version = "0.4.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0bad00257d07be169d870ab665980b06cdb366d792ad690bf2e76876dc503455"
+checksum = "f23ff5ef2b80d608d61efee834934d862cd92461afc0560dedf493e4c033738b"
dependencies = [
- "hermit-abi 0.3.3",
- "rustix",
+ "hermit-abi",
+ "libc",
"windows-sys 0.52.0",
]
[[package]]
name = "is_ci"
-version = "1.1.1"
+version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "616cde7c720bb2bb5824a224687d8f77bfd38922027f01d825cd7453be5099fb"
+checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45"
[[package]]
name = "itertools"
-version = "0.11.0"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57"
+checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
dependencies = [
"either",
]
@@ -1261,9 +1168,9 @@
[[package]]
name = "js-sys"
-version = "0.3.66"
+version = "0.3.68"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
+checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee"
dependencies = [
"wasm-bindgen",
]
@@ -1279,9 +1186,9 @@
[[package]]
name = "libc"
-version = "0.2.151"
+version = "0.2.153"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
+checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
[[package]]
name = "libm"
@@ -1300,17 +1207,6 @@
]
[[package]]
-name = "libredox"
-version = "0.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8"
-dependencies = [
- "bitflags 2.4.1",
- "libc",
- "redox_syscall",
-]
-
-[[package]]
name = "linked-hash-map"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1318,9 +1214,9 @@
[[package]]
name = "linux-raw-sys"
-version = "0.4.12"
+version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456"
+checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c"
[[package]]
name = "lock_api"
@@ -1385,9 +1281,9 @@
[[package]]
name = "miniz_oxide"
-version = "0.7.1"
+version = "0.7.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7"
+checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7"
dependencies = [
"adler",
]
@@ -1399,7 +1295,7 @@
checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
dependencies = [
"libc",
- "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasi",
"windows-sys 0.48.0",
]
@@ -1409,7 +1305,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2eb04e9c688eff1c89d72b407f168cf79bb9e867a9d3323ed6c01519eb9cc053"
dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
"cfg-if",
"libc",
]
@@ -1460,26 +1356,31 @@
"num-integer",
"num-iter",
"num-traits",
- "rand 0.8.5",
+ "rand",
"smallvec",
"zeroize",
]
[[package]]
+name = "num-conv"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+
+[[package]]
name = "num-integer"
-version = "0.1.45"
+version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "225d3389fb3509a24c93f5c29eb6bde2586b98d9f016636dff58d7c6f7569cd9"
+checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
dependencies = [
- "autocfg",
"num-traits",
]
[[package]]
name = "num-iter"
-version = "0.1.43"
+version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
+checksum = "d869c01cc0c455284163fd0092f1f93835385ccab5a98a0dcc497b2f8bf055a9"
dependencies = [
"autocfg",
"num-integer",
@@ -1488,9 +1389,9 @@
[[package]]
name = "num-traits"
-version = "0.2.17"
+version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
+checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
dependencies = [
"autocfg",
"libm",
@@ -1502,7 +1403,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43"
dependencies = [
- "hermit-abi 0.3.3",
+ "hermit-abi",
"libc",
]
@@ -1535,11 +1436,10 @@
[[package]]
name = "openssh"
-version = "0.10.2"
+version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8274f2bf1fc3785406a3ff07c92c15590c00e84efb883da77b671562ca9a6115"
+checksum = "cab71dc3fc68747816c7eecdffcede064d6bac9621fd658bf1ab5414e91558a3"
dependencies = [
- "dirs",
"libc",
"once_cell",
"shell-escape",
@@ -1548,12 +1448,6 @@
"tokio",
"tokio-pipe",
]
-
-[[package]]
-name = "option-ext"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "overload"
@@ -1563,21 +1457,19 @@
[[package]]
name = "owo-colors"
-version = "3.5.0"
+version = "4.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1b04fb49957986fdce4d6ee7a65027d55d4b6d2265e5848bbb507b58ccfdb6f"
+checksum = "caff54706df99d2a78a5a4e3455ff45448d81ef1bb63c22cd14052ca0e993a3f"
dependencies = [
"supports-color",
]
[[package]]
name = "papergrid"
-version = "0.10.0"
+version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2ccbe15f2b6db62f9a9871642746427e297b0ceb85f9a7f1ee5ff47d184d0c8"
+checksum = "9ad43c07024ef767f9160710b3a6773976194758c7919b17e63b863db0bdf7fb"
dependencies = [
- "ansi-str",
- "ansitok",
"bytecount",
"fnv",
"unicode-width",
@@ -1608,11 +1500,12 @@
[[package]]
name = "pbkdf2"
-version = "0.11.0"
+version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83a0692ec44e4cf1ef28ca317f14f8f07da2d95ec3fa01f86e4467b725e60917"
+checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2"
dependencies = [
- "digest 0.10.7",
+ "digest",
+ "hmac",
]
[[package]]
@@ -1644,22 +1537,22 @@
[[package]]
name = "pin-project"
-version = "1.1.3"
+version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422"
+checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0"
dependencies = [
"pin-project-internal",
]
[[package]]
name = "pin-project-internal"
-version = "1.1.3"
+version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
+checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.49",
]
[[package]]
@@ -1676,27 +1569,32 @@
[[package]]
name = "pkcs1"
-version = "0.4.1"
+version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eff33bdbdfc54cc98a2eca766ebdec3e1b8fb7387523d5c9c9a2891da856f719"
+checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
dependencies = [
"der",
"pkcs8",
"spki",
- "zeroize",
]
[[package]]
name = "pkcs8"
-version = "0.9.0"
+version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9eca2c590a5f85da82668fa685c09ce2888b9430e83299debf1f34b65fd4a4ba"
+checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
dependencies = [
"der",
"spki",
]
[[package]]
+name = "platforms"
+version = "3.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c"
+
+[[package]]
name = "poly1305"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1763,9 +1661,9 @@
[[package]]
name = "proc-macro2"
-version = "1.0.75"
+version = "1.0.78"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708"
+checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae"
dependencies = [
"unicode-ident",
]
@@ -1788,19 +1686,6 @@
"log",
"parking_lot",
"scheduled-thread-pool",
-]
-
-[[package]]
-name = "rand"
-version = "0.7.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03"
-dependencies = [
- "getrandom 0.1.16",
- "libc",
- "rand_chacha 0.2.2",
- "rand_core 0.5.1",
- "rand_hc",
]
[[package]]
@@ -1810,18 +1695,8 @@
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
- "rand_chacha 0.3.1",
- "rand_core 0.6.4",
-]
-
-[[package]]
-name = "rand_chacha"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402"
-dependencies = [
- "ppv-lite86",
- "rand_core 0.5.1",
+ "rand_chacha",
+ "rand_core",
]
[[package]]
@@ -1831,16 +1706,7 @@
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
- "rand_core 0.6.4",
-]
-
-[[package]]
-name = "rand_core"
-version = "0.5.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19"
-dependencies = [
- "getrandom 0.1.16",
+ "rand_core",
]
[[package]]
@@ -1848,17 +1714,8 @@
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
-dependencies = [
- "getrandom 0.2.11",
-]
-
-[[package]]
-name = "rand_hc"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c"
dependencies = [
- "rand_core 0.5.1",
+ "getrandom",
]
[[package]]
@@ -1868,28 +1725,17 @@
checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
dependencies = [
"bitflags 1.3.2",
-]
-
-[[package]]
-name = "redox_users"
-version = "0.4.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4"
-dependencies = [
- "getrandom 0.2.11",
- "libredox",
- "thiserror",
]
[[package]]
name = "regex"
-version = "1.10.2"
+version = "1.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
+checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15"
dependencies = [
"aho-corasick",
"memchr",
- "regex-automata 0.4.3",
+ "regex-automata 0.4.5",
"regex-syntax 0.8.2",
]
@@ -1904,9 +1750,9 @@
[[package]]
name = "regex-automata"
-version = "0.4.3"
+version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
+checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
dependencies = [
"aho-corasick",
"memchr",
@@ -1950,8 +1796,8 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94"
dependencies = [
- "base64 0.21.5",
- "bitflags 2.4.1",
+ "base64",
+ "bitflags 2.4.2",
"serde",
"serde_derive",
]
@@ -1971,30 +1817,29 @@
[[package]]
name = "rsa"
-version = "0.7.2"
+version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "094052d5470cbcef561cb848a7209968c9f12dfa6d668f4bca048ac5de51099c"
+checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc"
dependencies = [
- "byteorder",
- "digest 0.10.7",
+ "const-oid",
+ "digest",
"num-bigint-dig",
"num-integer",
- "num-iter",
"num-traits",
"pkcs1",
"pkcs8",
- "rand_core 0.6.4",
+ "rand_core",
"signature",
- "smallvec",
+ "spki",
"subtle",
"zeroize",
]
[[package]]
name = "rust-embed"
-version = "6.8.1"
+version = "8.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a36224c3276f8c4ebc8c20f158eca7ca4359c8db89991c4925132aaaf6702661"
+checksum = "a82c0bbc10308ed323529fd3c1dce8badda635aa319a5ff0e6466f33b8101e3f"
dependencies = [
"rust-embed-impl",
"rust-embed-utils",
@@ -2003,22 +1848,22 @@
[[package]]
name = "rust-embed-impl"
-version = "6.8.1"
+version = "8.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49b94b81e5b2c284684141a2fb9e2a31be90638caf040bf9afbc5a0416afe1ac"
+checksum = "6227c01b1783cdfee1bcf844eb44594cd16ec71c35305bf1c9fb5aade2735e16"
dependencies = [
"proc-macro2",
"quote",
"rust-embed-utils",
- "syn 2.0.48",
+ "syn 2.0.49",
"walkdir",
]
[[package]]
name = "rust-embed-utils"
-version = "7.8.1"
+version = "8.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9d38ff6bf570dc3bb7100fce9f7b60c33fa71d80e88da3f2580df4ff2bdded74"
+checksum = "8cb0a25bfbb2d4b4402179c2cf030387d9990857ce08a32592c6238db9fa8665"
dependencies = [
"sha2",
"walkdir",
@@ -2037,12 +1882,21 @@
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
+name = "rustc_version"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
+dependencies = [
+ "semver",
+]
+
+[[package]]
name = "rustix"
-version = "0.38.28"
+version = "0.38.31"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "72e572a5e8ca657d7366229cdde4bd14c4eb5499a9573d4d366fe1b599daa316"
+checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
dependencies = [
- "bitflags 2.4.1",
+ "bitflags 2.4.2",
"errno",
"libc",
"linux-raw-sys",
@@ -2090,11 +1944,10 @@
[[package]]
name = "scrypt"
-version = "0.10.0"
+version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9f9e24d2b632954ded8ab2ef9fea0a0c769ea56ea98bddbafbad22caeeadf45d"
+checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f"
dependencies = [
- "hmac",
"pbkdf2",
"salsa20",
"sha2",
@@ -2125,10 +1978,16 @@
checksum = "58bf37232d3bb9a2c4e641ca2a11d83b5062066f88df7fed36c28772046d65ba"
[[package]]
+name = "semver"
+version = "1.0.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b97ed7a9823b74f99c7742f5336af7be5ecd3eeafcb1507d1fa93347b1d589b0"
+
+[[package]]
name = "serde"
-version = "1.0.193"
+version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89"
+checksum = "870026e60fa08c69f064aa766c10f10b1d62db9ccd4d0abb206472bee0ce3b32"
dependencies = [
"serde_derive",
]
@@ -2144,20 +2003,20 @@
[[package]]
name = "serde_derive"
-version = "1.0.193"
+version = "1.0.196"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3"
+checksum = "33c85360c95e7d137454dc81d9a4ed2b8efd8fbe19cee57357b32b9771fccb67"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.49",
]
[[package]]
name = "serde_json"
-version = "1.0.108"
+version = "1.0.113"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
+checksum = "69801b70b1c3dac963ecb03a364ba0ceda9cf60c71cfe475e99864759c8b8a79"
dependencies = [
"itoa",
"ryu",
@@ -2181,7 +2040,7 @@
dependencies = [
"cfg-if",
"cpufeatures",
- "digest 0.10.7",
+ "digest",
]
[[package]]
@@ -2201,9 +2060,9 @@
[[package]]
name = "shlex"
-version = "1.2.0"
+version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380"
+checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
[[package]]
name = "signal-hook-registry"
@@ -2216,12 +2075,12 @@
[[package]]
name = "signature"
-version = "1.6.4"
+version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74233d3b3b2f6d4b006dc19dee745e73e2a6bfb6f93607cd3b02bd5b00797d7c"
+checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
dependencies = [
- "digest 0.10.7",
- "rand_core 0.6.4",
+ "digest",
+ "rand_core",
]
[[package]]
@@ -2235,9 +2094,9 @@
[[package]]
name = "smallvec"
-version = "1.11.2"
+version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970"
+checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
[[package]]
name = "smol_str"
@@ -2266,9 +2125,9 @@
[[package]]
name = "spki"
-version = "0.6.0"
+version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "67cf02bbac7a337dc36e4f5a693db6c21e7863f45070f7064577eb4367a3212b"
+checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
dependencies = [
"base64ct",
"der",
@@ -2281,6 +2140,12 @@
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
+name = "strsim"
+version = "0.11.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
+
+[[package]]
name = "subtle"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2288,11 +2153,11 @@
[[package]]
name = "supports-color"
-version = "1.3.1"
+version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ba6faf2ca7ee42fdd458f4347ae0a9bd6bcc445ad7cb57ad82b383f18870d6f"
+checksum = "d6398cde53adc3c4557306a96ce67b302968513830a77a95b2b17305d9719a89"
dependencies = [
- "atty",
+ "is-terminal",
"is_ci",
]
@@ -2309,9 +2174,9 @@
[[package]]
name = "syn"
-version = "2.0.48"
+version = "2.0.49"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f"
+checksum = "915aea9e586f80826ee59f8453c1101f9d1c4b3964cd2460185ee8e299ada496"
dependencies = [
"proc-macro2",
"quote",
@@ -2320,12 +2185,10 @@
[[package]]
name = "tabled"
-version = "0.14.0"
+version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfe9c3632da101aba5131ed63f9eed38665f8b3c68703a6bb18124835c1a5d22"
+checksum = "4c998b0c8b921495196a48aabaf1901ff28be0760136e31604f7967b0792050e"
dependencies = [
- "ansi-str",
- "ansitok",
"papergrid",
"tabled_derive",
"unicode-width",
@@ -2333,9 +2196,9 @@
[[package]]
name = "tabled_derive"
-version = "0.6.0"
+version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99f688a08b54f4f02f0a3c382aefdb7884d3d69609f785bd253dc033243e3fe4"
+checksum = "4c138f99377e5d653a371cdad263615634cfc8467685dfe8e73e2b8e98f44b17"
dependencies = [
"heck",
"proc-macro-error",
@@ -2346,27 +2209,17 @@
[[package]]
name = "tempfile"
-version = "3.9.0"
+version = "3.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa"
+checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67"
dependencies = [
"cfg-if",
"fastrand",
- "redox_syscall",
"rustix",
"windows-sys 0.52.0",
]
[[package]]
-name = "termcolor"
-version = "1.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449"
-dependencies = [
- "winapi-util",
-]
-
-[[package]]
name = "terminal_size"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2384,22 +2237,22 @@
[[package]]
name = "thiserror"
-version = "1.0.53"
+version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2cd5904763bad08ad5513ddbb12cf2ae273ca53fa9f68e843e236ec6dfccc09"
+checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "1.0.53"
+version = "1.0.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3dcf4a824cce0aeacd6f38ae6f24234c8e80d68632338ebaa1443b5df9e29e19"
+checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.49",
]
[[package]]
@@ -2414,11 +2267,12 @@
[[package]]
name = "time"
-version = "0.3.31"
+version = "0.3.34"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f657ba42c3f86e7680e53c8cd3af8abbe56b5491790b46e22e19c0d57463583e"
+checksum = "c8248b6521bb14bc45b4067159b9b6ad792e2d6d754d6c41fb50e29fefe38749"
dependencies = [
"deranged",
+ "num-conv",
"powerfmt",
"serde",
"time-core",
@@ -2433,10 +2287,11 @@
[[package]]
name = "time-macros"
-version = "0.2.16"
+version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26197e33420244aeb70c3e8c78376ca46571bc4e701e4791c2cd9f57dcb3a43f"
+checksum = "7ba3a3ef41e6672a2f0f001392bb5dcd3ff0a9992d618ca761a11c3121547774"
dependencies = [
+ "num-conv",
"time-core",
]
@@ -2451,9 +2306,9 @@
[[package]]
name = "tokio"
-version = "1.35.1"
+version = "1.36.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
+checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
dependencies = [
"backtrace",
"bytes",
@@ -2475,7 +2330,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.49",
]
[[package]]
@@ -2513,9 +2368,9 @@
[[package]]
name = "toml"
-version = "0.8.8"
+version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35"
+checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290"
dependencies = [
"serde",
"serde_spanned",
@@ -2534,9 +2389,9 @@
[[package]]
name = "toml_edit"
-version = "0.21.0"
+version = "0.22.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03"
+checksum = "2c1b5fd4128cc8d3e0cb74d4ed9a9cc7c7284becd4df68f5f940e1ad123606f6"
dependencies = [
"indexmap",
"serde",
@@ -2564,7 +2419,7 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.49",
]
[[package]]
@@ -2716,18 +2571,7 @@
"itoa",
"log",
"unicode-width",
- "vte 0.11.1",
-]
-
-[[package]]
-name = "vte"
-version = "0.10.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6cbce692ab4ca2f1f3047fcf732430249c0e971bfdd2b234cf2c47ad93af5983"
-dependencies = [
- "arrayvec 0.5.2",
- "utf8parse",
- "vte_generate_state_changes",
+ "vte",
]
[[package]]
@@ -2736,7 +2580,7 @@
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197"
dependencies = [
- "arrayvec 0.7.4",
+ "arrayvec",
"utf8parse",
"vte_generate_state_changes",
]
@@ -2763,21 +2607,15 @@
[[package]]
name = "wasi"
-version = "0.9.0+wasi-snapshot-preview1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
-
-[[package]]
-name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
-version = "0.2.89"
+version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
+checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
@@ -2785,24 +2623,24 @@
[[package]]
name = "wasm-bindgen-backend"
-version = "0.2.89"
+version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
+checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.49",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.89"
+version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
+checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -2810,22 +2648,22 @@
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.89"
+version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
+checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.49",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.89"
+version = "0.2.91"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
+checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838"
[[package]]
name = "winapi"
@@ -2869,15 +2707,6 @@
[[package]]
name = "windows-sys"
-version = "0.45.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0"
-dependencies = [
- "windows-targets 0.42.2",
-]
-
-[[package]]
-name = "windows-sys"
version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
@@ -2892,21 +2721,6 @@
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
dependencies = [
"windows-targets 0.52.0",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071"
-dependencies = [
- "windows_aarch64_gnullvm 0.42.2",
- "windows_aarch64_msvc 0.42.2",
- "windows_i686_gnu 0.42.2",
- "windows_i686_msvc 0.42.2",
- "windows_x86_64_gnu 0.42.2",
- "windows_x86_64_gnullvm 0.42.2",
- "windows_x86_64_msvc 0.42.2",
]
[[package]]
@@ -2938,12 +2752,6 @@
"windows_x86_64_gnullvm 0.52.0",
"windows_x86_64_msvc 0.52.0",
]
-
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8"
[[package]]
name = "windows_aarch64_gnullvm"
@@ -2959,12 +2767,6 @@
[[package]]
name = "windows_aarch64_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43"
-
-[[package]]
-name = "windows_aarch64_msvc"
version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
@@ -2974,12 +2776,6 @@
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f"
[[package]]
name = "windows_i686_gnu"
@@ -2992,12 +2788,6 @@
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060"
[[package]]
name = "windows_i686_msvc"
@@ -3010,12 +2800,6 @@
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
-
-[[package]]
-name = "windows_x86_64_gnu"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36"
[[package]]
name = "windows_x86_64_gnu"
@@ -3028,12 +2812,6 @@
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3"
[[package]]
name = "windows_x86_64_gnullvm"
@@ -3046,12 +2824,6 @@
version = "0.52.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
-
-[[package]]
-name = "windows_x86_64_msvc"
-version = "0.42.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0"
[[package]]
name = "windows_x86_64_msvc"
@@ -3067,21 +2839,22 @@
[[package]]
name = "winnow"
-version = "0.5.31"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "97a4882e6b134d6c28953a387571f1acdd3496830d5e36c5e3a1075580ea641c"
+checksum = "d90f4e0f530c4c69f62b80d839e9ef3855edc9cba471a160c4d692deed62b401"
dependencies = [
"memchr",
]
[[package]]
name = "x25519-dalek"
-version = "1.1.1"
+version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a0c105152107e3b96f6a00a65e86ce82d9b125230e1c4302940eca58ff71f4f"
+checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277"
dependencies = [
"curve25519-dalek",
- "rand_core 0.5.1",
+ "rand_core",
+ "serde",
"zeroize",
]
@@ -3108,5 +2881,5 @@
dependencies = [
"proc-macro2",
"quote",
- "syn 2.0.48",
+ "syn 2.0.49",
]
Cargo.tomldiffbeforeafterboth--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,5 +6,5 @@
nixlike = { path = "./crates/nixlike" }
better-command = { path = "./crates/better-command" }
bifrostlink = "0.1.0"
-uuid = { version = "1.3.3", features = ["v4"] }
-tokio = { version = "1.33.0", features = ["fs", "rt", "macros", "sync", "time", "rt-multi-thread"] }
+uuid = { version = "1.7.0", features = ["v4"] }
+tokio = { version = "1.36.0", features = ["fs", "rt", "macros", "sync", "time", "rt-multi-thread"] }
README.adocdiffbeforeafterboth--- a/README.adoc
+++ b/README.adoc
@@ -11,3 +11,164 @@
- Modules can configure multiple hosts at once (I.e for wireguard/kubernetes installation)
- Secrets can be securely stored in Git (No one except target hosts can decrypt them), automatically regenerated, reencrypted, etc.
- Automatic rollback on deployment failure, which will work, as long as system is passing initrd stage (So still be carefull with root filesystem mount)
+
+== Secret generator example
+
+TODO:: This section should into some kind of fleet documentation... But as there is none, it is just left here as-is.
+
+=== Quickly run securely setup gitlab
+
+[source,nix]
+----
+{config, ...}: {
+ secrets = let ownership = { owner = "gitlab"; group = "gitlab"; }; in {
+ gitlab-initial-root = {
+ generator = {mkPassword}: mkPassword {};
+ } // ownership;
+ gitlab-secret = {
+ generator = {mkPassword}: mkPassword {};
+ } // ownership;
+ gitlab-otp = {
+ generator = {mkPassword}: mkPassword {};
+ } // ownership;
+ gitlab-db = {
+ generator = {mkPassword}: mkPassword {};
+ } // ownership;
+ gitlab-jws = {
+ generator = {mkRsa}: mkRsa {};
+ } // ownership;
+ };
+ services.gitlab = let secrets = config.secrets; in {
+ enable = true;
+ initialRootPasswordFile = secrets.gitlab-initial-root.secretPath;
+ secrets = {
+ secretFile = secrets.gitlab-secret.secretPath;
+ otpFile = secrets.gitlab-otp.secretPath;
+ dbFile = secrets.gitlab-db.secretPath;
+ jwsFile = secrets.gitlab-jws.secretPath;
+ };
+ };
+}
+----
+
+=== Securely initialize kubernetes secrets
+
+In my homelab and clusters, I almost always have some sort of HSM, and to issue new kubernetes certs I directly connect to it.
+This setup should probably split into multiple steps, where I allow target machine to generate CSR, then copy it to the HSM machine, and then sign it there... But this is just the plan.
+I want to build ansible-like script execution in fleet for this kind of tasks.
+
+[source,nix]
+----
+{...}: {
+ # First I define required secret generators:
+ nixpkgs.overlays = [
+ (final: prev: let
+ lib = final.lib;
+ in {
+ readKubernetesCa = {impureOn}:
+ final.mkImpureSecretGenerator ''
+ cd ~/ca
+
+ cert=kubernetes-intermediateCA.crt
+
+ expires_at=$(openssl x509 -in $cert -noout -enddate | cut -d= -f2 | xargs -I{} date -u -d {} +"%Y-%m-%dT%H:%M:%S.%NZ")
+ echo -n $expires_at > $out/expires_at
+
+ cat $cert > $out/public
+ ''
+ impureOn;
+ mkKubernetesCert = {
+ subj,
+ sans ? [],
+ impureOn,
+ }:
+ final.mkImpureSecretGenerator ''
+ cd ~/ca
+
+ params=$(sudo mktemp)
+ csr=$(sudo mktemp)
+ cert=$(sudo mktemp)
+ sudo openssl ecparam -genkey -name secp384r1 -out $params
+ sudo openssl req -new -key $params \
+ -subj "${lib.strings.concatStringsSep "" (lib.attrsets.mapAttrsToList (k: v: "/${k}=${v}") subj)}" \
+ ${lib.optionalString (sans != []) "-addext \"subjectAltName = ${lib.strings.concatStringsSep "," sans}\""} \
+ -out $csr
+ sudo hsms x509 -req -days 365 -in $csr -CA kubernetes-intermediateCA.crt -CAkey "pkcs11:object=[CENSORED] Kubernetes Intermediate CA;type=private" -CAcreateserial -copy_extensions copy -out $cert
+
+ expires_at=$(sudo openssl x509 -in $cert -noout -enddate | cut -d= -f2 | xargs -I{} date -u -d {} +"%Y-%m-%dT%H:%M:%S.%NZ")
+ echo -n $expires_at > $out/expires_at
+
+ sudo cat $params | encrypt > $out/secret
+ sudo cat $cert > $out/public
+ ''
+ impureOn;
+ })
+ ];
+ # Those secret generators are impure, thus they are run in system environment.
+ # Probably there needs to be a dedicated user for that kind of tasks, but this is my current setup, don't judge.
+ # I write a couple of scripts for executing openssl with HSM.
+ environment.systemPackages = [
+ pkgs.openssl.bin
+ (pkgs.writeShellApplication {
+ name = "hsms";
+ text = ''
+ set -eu
+ export OPENSSL_CONF=${openssl-conf}
+ # Yay, using secrets to generate secrets!
+ HSM_PIN=$(cat ${config.secrets.hsm-pin.secretPath})
+ exec ${pkgs.openssl}/bin/openssl "$@" -keyform=engine -CAkeyform=engine -engine=pkcs11 -passin=pass:"$HSM_PIN"
+ '';
+ })
+ (pkgs.writeShellApplication {
+ name = "hsmt";
+ text = ''
+ set -eu
+ HSM_PIN=$(cat ${config.secrets.hsm-pin.secretPath})
+ exec ${pkgs.opensc}/bin/pkcs11-tool -l --pin="$HSM_PIN" "$@"
+ '';
+ })
+ ];
+ # And finally, I have secrets, which are shared between machines.
+ # Note that this example is somewhat wrong, as this goes not into the machine configuration, but to fleet configuration.
+ sharedSecrets = {
+ "ca.pem" = {
+ # This is just the public key, no need to regenerate it to change owner list
+ regenerateOnOwnerAdded = false;
+ # For secret regeneration/reencryption, we need to specify which machines SHOULD have it.
+ expectedOwners = ["controlplane-1" "controlplane-2" "worker-1" "worker-2"];
+ generator = {readKubernetesCa}:
+ readKubernetesCa {
+ impureOn = "[CENSORED]";
+ };
+ };
+ "kube-admin.pem" = {
+ regenerateOnOwnerAdded = false;
+ expectedOwners = ["cluster-admin"];
+ generator = {mkKubernetesCert}:
+ mkKubernetesCert {
+ subj = {
+ CN = "admin";
+ O = "system:masters";
+ };
+ impureOn = "[CENSORED]";
+ };
+ };
+ "kube-apiserver.pem" = {
+ # This secret depends on machine SANS, so if owner list has been changed, then we need to regenerate it.
+ # However, SANS dependency is in fact handled by secret seed, and secret is regenerated if the seed is changed...
+ #
+ # In this case regeneration is added as a half-assed security measure, as if apiserver is removed, we don't
+ # want for it to be able to pretend like it is a valid server.
+ #
+ # However, certificate revokation is complicated in my setup, and I can't show it here.
+ regenerateOnOwnerAdded = true;
+ expectedOwners = ["controlplane-1" "controlplane-2"];
+ generator = {mkKubernetesCert}:
+ mkKubernetesCert {
+ inherit sans;
+ subj.CN = "kubernetes";
+ impureOn = "[CENSORED]";
+ };
+ };
+}
+----
cmds/fleet/Cargo.tomldiffbeforeafterboth--- a/cmds/fleet/Cargo.toml
+++ b/cmds/fleet/Cargo.toml
@@ -12,17 +12,17 @@
anyhow = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
-time = { version = "0.3.30", features = ["serde"] }
-tempfile = "3.8"
-once_cell = "1.18.0"
-hostname = "0.3.1"
-age-core = "0.9.0"
-peg = "0.8.2"
-age = { version = "0.9.2", features = ["ssh", "armor"] }
-base64 = "0.21.5"
-chrono = { version = "0.4.31", features = ["serde"] }
-z85 = "3.0.5"
-clap = { version = "4.4.7", features = [
+time = { version = "0.3", features = ["serde"] }
+tempfile = "3.10"
+once_cell = "1.19"
+hostname = "0.3"
+age-core = "0.10"
+peg = "0.8"
+age = { version = "0.10", features = ["ssh", "armor"] }
+base64 = "0.21"
+chrono = { version = "0.4", features = ["serde"] }
+z85 = "3.0"
+clap = { version = "4.5", features = [
"derive",
"env",
"wrap_help",
@@ -30,18 +30,18 @@
] }
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["fmt", "env-filter"] }
-tokio-util = { version = "0.7.10", features = ["codec"] }
-async-trait = "0.1.74"
-futures = "0.3.29"
-tracing-indicatif = "0.3.5"
-indicatif = "0.17.7"
-itertools = "0.11.0"
-shlex = "1.2.0"
-tabled = { version = "0.14.0", features = ["color"] }
-owo-colors = { version = "3.5.0", features = ["supports-color", "supports-colors"] }
+tokio-util = { version = "0.7", features = ["codec"] }
+async-trait = "0.1"
+futures = "0.3"
+tracing-indicatif = "0.3"
+indicatif = "0.17"
+itertools = "0.12"
+shlex = "1.3"
+tabled = { version = "0.15" }
+owo-colors = { version = "4.0", features = ["supports-color", "supports-colors"] }
r2d2 = "0.8.10"
-abort-on-drop = "0.2.2"
-unindent = "0.2.3"
-regex = "1.10.2"
-openssh = "0.10.1"
-human-repr = "1.1.0"
+abort-on-drop = "0.2"
+unindent = "0.2"
+regex = "1.10"
+openssh = "0.10"
+human-repr = "1.1"
cmds/fleet/src/cmds/secrets/mod.rsdiffbeforeafterboth--- a/cmds/fleet/src/cmds/secrets/mod.rs
+++ b/cmds/fleet/src/cmds/secrets/mod.rs
@@ -1,5 +1,6 @@
use crate::{
better_nix_eval::Field,
+ command::MyCommand,
fleetdata::{FleetSecret, FleetSharedSecret, SecretData},
host::Config,
nix_go, nix_go_json,
@@ -8,14 +9,16 @@
use chrono::{DateTime, Utc};
use clap::Parser;
use owo_colors::OwoColorize;
-use serde::Deserialize;
+use serde::{de::DeserializeOwned, Deserialize};
use std::{
collections::{BTreeSet, HashSet},
io::{self, Cursor, Read},
- path::PathBuf,
+ path::{Path, PathBuf},
+ str::FromStr,
};
use tabled::{Table, Tabled};
-use tokio::fs::read_to_string;
+use tempfile::tempdir;
+use tokio::fs::{self, read_to_string};
use tracing::{error, info, info_span, warn, Instrument};
#[derive(Parser)]
@@ -67,6 +70,10 @@
#[clap(long)]
plaintext: bool,
},
+ ReadPublic {
+ name: String,
+ machine: String,
+ },
UpdateShared {
name: String,
@@ -151,8 +158,89 @@
#[serde(rename_all = "camelCase")]
enum GeneratorKind {
Impure,
+ Pure,
}
+async fn generate_pure(
+ config: &Config,
+ _display_name: &str,
+ secret: Field,
+ default_generator: Field,
+ owners: &[String],
+) -> Result<FleetSecret> {
+ // TODO: pure secrets are supposed to be generated by nix daemon itself,
+ // inside of a sandbox... But we aren't here yet.
+ let config_field = &config.config_unchecked_field;
+ let generator = nix_go!(secret.generator);
+ let default_pkgs = &config.default_pkgs;
+
+ let call_package = nix_go!(default_pkgs.callPackage);
+
+ let generator = nix_go!(call_package(generator)(Obj {}));
+ let generator = generator.build().await?;
+ let generator = generator
+ .get("out")
+ .ok_or_else(|| anyhow!("missing generate out"))?;
+
+ let mut recipients = String::new();
+ for owner in owners {
+ let key = config.key(owner).await?;
+ recipients.push_str(&format!("-r \"{key}\" "));
+ }
+ recipients.push_str("-e");
+
+ let out = tempdir()?;
+
+ let mut gen = MyCommand::new(generator);
+ gen.env("rageArgs", recipients);
+ gen.env(
+ "out",
+ out.path().to_str().expect("sane tempdir should be utf-8"),
+ );
+ gen.run().await.context("impure generator")?;
+
+ {
+ let mut marker_path = out.path().to_owned();
+ marker_path.push("marker");
+ let marker = fs::read_to_string(&marker_path).await?;
+ ensure!(marker == "SUCCESS", "generation not succeeded");
+ }
+
+ let mut public_path = out.path().to_owned();
+ public_path.push("public");
+ let mut secret_path = out.path().to_owned();
+ secret_path.push("secret");
+ let public = fs::read_to_string(&public_path).await.ok();
+ let secret = fs::read(&secret_path).await.ok();
+ if let Some(secret) = &secret {
+ ensure!(
+ age::Decryptor::new(Cursor::new(&secret)).is_ok(),
+ "builder produced non-encrypted value as secret, this is highly insecure, and not allowed."
+ );
+ }
+
+ let mut created_at_path = out.path().to_owned();
+ created_at_path.push("created_at");
+ let mut expires_at_path = out.path().to_owned();
+ expires_at_path.push("expires_at");
+
+ async fn read_value<T: FromStr>(path: &Path) -> Result<T> {
+ dbg!(path);
+ let raw = fs::read(path).await?;
+ let raw = String::from_utf8(raw)?;
+ raw.parse().map_err(|_| anyhow!("fromStr failed"))
+ }
+
+ let created_at = read_value(&created_at_path).await?;
+ let expires_at = read_value(&expires_at_path).await.ok();
+
+ Ok(FleetSecret {
+ created_at,
+ expires_at,
+ public,
+ secret: secret.map(SecretData),
+ })
+}
async fn generate_impure(
config: &Config,
_display_name: &str,
@@ -254,6 +342,9 @@
GeneratorKind::Impure => {
generate_impure(config, display_name, secret, default_generator, owners).await
}
+ GeneratorKind::Pure => {
+ generate_pure(config, display_name, secret, default_generator, owners).await
+ }
}
}
async fn generate_shared(
@@ -357,6 +448,8 @@
expires_at,
re_add,
} => {
+ // TODO: Forbid updating secrets with set expectedOwners (= not user-managed).
+
let exists = config.has_shared(&name);
if exists && !force && !re_add {
bail!("secret already defined");
@@ -456,6 +549,16 @@
println!("{}", z85::encode(&data));
}
}
+ Secret::ReadPublic {
+ name,
+ machine,
+ } => {
+ let secret = config.host_secret(&machine, &name)?;
+ let Some(public) = secret.public else {
+ bail!("no secret {name}");
+ };
+ print!("{public}");
+ }
Secret::UpdateShared {
name,
machines,
@@ -463,6 +566,8 @@
remove_machines,
prefer_identities,
} => {
+ // TODO: Forbid updating secrets with set expectedOwners (= not user-managed).
+
let secret = config.shared_secret(&name)?;
if secret.secret.secret.is_none() {
bail!("no secret");
cmds/fleet/src/main.rsdiffbeforeafterboth--- a/cmds/fleet/src/main.rs
+++ b/cmds/fleet/src/main.rs
@@ -11,9 +11,8 @@
mod fleetdata;
-use std::ffi::OsString;
-use std::process::exit;
use std::time::Duration;
+use std::{ffi::OsString, process::ExitCode};
use anyhow::{bail, Result};
use clap::Parser;
@@ -62,6 +61,7 @@
path.push(entry.path());
let mut status = MyCommand::new("nix");
+ status.args(&config.nix_args);
status.arg("store").arg("prefetch-file").arg(path);
status.run_nix_string().instrument(span).await?;
Ok(())
@@ -118,7 +118,11 @@
return;
};
let pos = state.pos();
- let _ = write!(writer, "{} / {}", pos.human_count_bare(), len.human_count_bare());
+ if pos > len {
+ let _ = write!(writer, "{}", pos.human_count_bare());
+ } else {
+ let _ = write!(writer, "{} / {}", pos.human_count_bare(), len.human_count_bare());
+ }
})
.with_key(
"color_start",
@@ -151,7 +155,7 @@
tracing_subscriber::fmt::layer()
.without_time()
.with_target(true)
- .with_writer(indicatif_layer.get_stderr_writer())
+ .with_writer(indicatif_layer.get_stdout_writer())
.with_filter(filter), // .withou,
)
.with(indicatif_layer)
@@ -159,12 +163,15 @@
}
#[tokio::main]
-async fn main() {
+async fn main() -> ExitCode {
setup_logging();
if let Err(e) = main_real().await {
+ // If I remove this line, the next error!() line gets eaten.
+ info!("fixme: this line gets eaten by tracing-indicatif on levels info+");
error!("{e:#}");
- exit(1);
+ return ExitCode::FAILURE;
}
+ ExitCode::SUCCESS
}
async fn main_real() -> Result<()> {
cmds/install-secrets/Cargo.tomldiffbeforeafterboth--- a/cmds/install-secrets/Cargo.toml
+++ b/cmds/install-secrets/Cargo.toml
@@ -4,18 +4,18 @@
edition = "2021"
[dependencies]
-age = { version = "0.9.2", features = ["ssh"] }
-anyhow = "1.0.75"
-env_logger = "0.10.0"
-log = "0.4.20"
+age = { version = "0.10.0", features = ["ssh"] }
+anyhow = "1.0.79"
+tracing-subscriber = "0.3"
+tracing = "0.1"
nix = {version = "0.27.1", features = ["user", "fs"]}
-serde = { version = "1.0.190", features = ["derive"] }
-serde_json = "1.0.107"
-clap = { version = "4.4.7", features = [
+serde = { version = "1.0.196", features = ["derive"] }
+serde_json = "1.0.113"
+clap = { version = "4.5.1", features = [
"derive",
"env",
"wrap_help",
"unicode",
] }
-tempfile = "3.8.1"
+tempfile = "3.10.0"
z85 = "3.0.5"
cmds/install-secrets/src/main.rsdiffbeforeafterboth1use age::{ssh::Identity as SshIdentity, ssh::Recipient as SshRecipient, Decryptor};2use age::{Encryptor, Identity, Recipient};3use anyhow::{anyhow, bail, Context, Result};4use clap::Parser;5use log::{error, info, warn};6use nix::sys::stat::Mode;7use nix::unistd::{User, Group, chown};8use serde::{Deserialize, Deserializer};9use std::fmt::{self, Display};10use std::fs::{self, File};11use std::io::{self, Cursor, Read, Write};12use std::iter;13use std::os::unix::prelude::PermissionsExt;14use std::path::Path;15use std::str::{from_utf8, FromStr};16use std::{collections::HashMap, path::PathBuf};1718#[derive(Clone, Debug)]19struct SecretWrapper(Vec<u8>);20impl Display for SecretWrapper {21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {22 let encoded = z85::encode(&self.0);23 write!(f, "{encoded}")24 }25}26impl FromStr for SecretWrapper {27 type Err = z85::DecodeError;2829 fn from_str(s: &str) -> Result<Self, Self::Err> {30 z85::decode(s).map(Self)31 }32}33impl<'de> Deserialize<'de> for SecretWrapper {34 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>35 where36 D: Deserializer<'de>,37 {38 let v = String::deserialize(deserializer)?;39 let de = z85::decode(v).map_err(|err| serde::de::Error::custom(err.to_string()))?;40 Ok(Self(de))41 }42}4344#[derive(Parser)]45#[clap(author)]46enum Opts {47 /// Install secrets from json specification48 Install { data: PathBuf },49 /// Reencrypt secret using host key, outputting in z85 encoded string50 Reencrypt {51 #[clap(long)]52 secret: SecretWrapper,53 #[clap(long)]54 targets: Vec<String>,55 },56 /// Decrypt secret using host key, outputting in z85 encoded string57 Decrypt {58 #[clap(long)]59 secret: SecretWrapper,60 /// Shoult decoded output be printed as plaintext, instead of z85?61 #[clap(long)]62 plaintext: bool,63 },64}6566#[derive(Deserialize)]67#[serde(rename_all = "camelCase")]68struct DataItem {69 group: String,70 mode: String,71 owner: String,7273 secret: Option<SecretWrapper>,74 public: Option<String>,7576 public_path: PathBuf,77 stable_public_path: PathBuf,7879 secret_path: PathBuf,80 stable_secret_path: PathBuf,81}8283type Data = HashMap<String, DataItem>;8485fn decrypt(input: &SecretWrapper, identity: &dyn Identity) -> Result<Vec<u8>> {86 let mut input = Cursor::new(&input.0);87 let decryptor = Decryptor::new(&mut input).context("failed to init decryptor")?;88 let decryptor = match decryptor {89 Decryptor::Recipients(r) => r,90 Decryptor::Passphrase(_) => bail!("should be recipients"),91 };92 let mut decryptor = decryptor93 .decrypt(iter::once(identity as &dyn age::Identity))94 .context("failed to decrypt, wrong key?")?;9596 let mut decrypted = Vec::new();97 decryptor98 .read_to_end(&mut decrypted)99 .context("failed to decrypt")?;100 Ok(decrypted)101}102fn encrypt(input: &[u8], targets: Vec<String>) -> Result<SecretWrapper> {103 let recipients = targets104 .into_iter()105 .map(|t| {106 SshRecipient::from_str(&t).map_err(|e| anyhow!("failed to parse recipient: {e:?}"))107 })108 .collect::<Result<Vec<SshRecipient>>>()?;109 let recipients = recipients110 .into_iter()111 .map(|v| Box::new(v) as Box<dyn Recipient + Send>)112 .collect::<Vec<_>>();113 let mut encrypted = vec![];114 let mut encryptor = Encryptor::with_recipients(recipients)115 .expect("recipients provided")116 .wrap_output(&mut encrypted)117 .expect("constructor should not fail");118 io::copy(&mut Cursor::new(input), &mut encryptor).expect("copy should not fail");119 encryptor.finish().context("failed to finish encryption")?;120 Ok(SecretWrapper(encrypted))121}122123fn init_secret(identity: &age::ssh::Identity, value: DataItem) -> Result<()> {124 if let Some(public) = &value.public {125 let mut hashed = File::create(&value.public_path)?;126 let stable_dir = value.stable_public_path.parent().expect("not root");127 let mut stable_temp =128 tempfile::NamedTempFile::new_in(stable_dir).context("failed to create tempfile")?;129 hashed.write_all(public.as_bytes())?;130 stable_temp.write_all(public.as_bytes())?;131 stable_temp.flush()?;132 fs::set_permissions(stable_temp.path(), fs::Permissions::from_mode(0o444))133 .context("perm")?;134 fs::set_permissions(&value.public_path, fs::Permissions::from_mode(0o444))135 .context("perm")?;136137 stable_temp138 .persist(value.stable_public_path)139 .context("failed to persist")?;140 }141 if value.secret.is_none() {142 info!("no secret data found");143 return Ok(());144 }145 let secret = value.secret.as_ref().unwrap();146147 let mode = Mode::from_bits(148 u32::from_str_radix(&value.mode, 8).context("failed to parse mode as octal")?,149 )150 .context("failed to parse mode")?;151 let user = User::from_name(&value.owner)152 .context("failed to get user")?153 .ok_or_else(|| anyhow!("user not found"))?;154 let group = Group::from_name(&value.group)155 .context("failed to get group")?156 .ok_or_else(|| anyhow!("group not found"))?;157158 let stable_dir = value.stable_secret_path.parent().expect("not root");159 let mut stable_temp =160 tempfile::NamedTempFile::new_in(stable_dir).context("failed to create tempfile")?;161 let mut hashed = File::create(&value.secret_path)?;162163 // File is owned by root, and only root can modify it164 let decrypted = decrypt(secret, identity)?;165 if decrypted.is_empty() {166 warn!("secret is decoded as empty, something is broken?");167 }168169 io::copy(&mut Cursor::new(&decrypted), &mut stable_temp)170 .context("failed to write decrypted file")?;171 io::copy(&mut Cursor::new(decrypted), &mut hashed).context("failed to write decrypted file")?;172173 // Make file owned by specified user and group, then change mode174 chown(stable_temp.path(), Some(user.uid), Some(group.gid))175 .context("failed to apply user/group")?;176 chown(&value.secret_path, Some(user.uid), Some(group.gid))177 .context("failed to apply user/group")?;178 fs::set_permissions(stable_temp.path(), fs::Permissions::from_mode(mode.bits())).unwrap();179 fs::set_permissions(&value.secret_path, fs::Permissions::from_mode(mode.bits())).unwrap();180 stable_temp181 .persist(value.stable_secret_path)182 .context("failed to persist")?;183184 Ok(())185}186187fn host_identity() -> anyhow::Result<SshIdentity> {188 let identity = SshIdentity::from_buffer(189 &mut Cursor::new(190 fs::read("/etc/ssh/ssh_host_ed25519_key").context("failed to read host private key")?,191 ),192 None,193 )194 .context("failed to parse identity")?;195 Ok(identity)196}197198fn install(data: &Path) -> anyhow::Result<()> {199 let data = fs::read(data).context("failed to read secrets data")?;200 let data_str = from_utf8(&data).context("failed to read data to string")?;201 let data: Data = serde_json::from_str(data_str).context("failed to parse data")?;202203 if !fs::metadata("/run/secrets")204 .map(|m| m.is_dir())205 .unwrap_or(false)206 {207 fs::create_dir("/run/secrets").context("failed to create secrets directory")?;208 }209210 let identity = host_identity()?;211212 let mut failed = false;213 for (name, value) in data {214 info!("initializing secret {name}");215 if let Err(e) = init_secret(&identity, value) {216 error!(217 "{:?}",218 e.context(format!("failed to initialize secret {}", name))219 );220 failed = true;221 }222 }223 if failed {224 bail!("one or more secrets failed");225 }226227 Ok(())228}229230fn main() -> anyhow::Result<()> {231 env_logger::Builder::new()232 .filter_level(log::LevelFilter::Info)233 .init();234235 let opts = Opts::parse();236237 match opts {238 Opts::Install { data } => install(&data),239 Opts::Reencrypt { secret, targets } => {240 let identity = host_identity()?;241 let decrypted = decrypt(&secret, &identity).context("during decryption")?;242 let encrypted = encrypt(&decrypted, targets).context("during re-encryption")?;243244 println!("{encrypted}");245 Ok(())246 }247 Opts::Decrypt { secret, plaintext } => {248 let identity = host_identity()?;249 let decrypted = decrypt(&secret, &identity).context("during decryption")?;250251 if plaintext {252 let s = String::from_utf8(decrypted).context("output is not utf8")?;253 print!("{s}");254 } else {255 println!("{}", SecretWrapper(decrypted));256 }257 Ok(())258 }259 }260}1use age::{ssh::Identity as SshIdentity, ssh::Recipient as SshRecipient, Decryptor};2use age::{Encryptor, Identity, Recipient};3use anyhow::{anyhow, bail, Context, Result};4use clap::Parser;5use nix::sys::stat::Mode;6use nix::unistd::{chown, Group, User};7use serde::{Deserialize, Deserializer};8use std::fmt::{self, Display};9use std::fs::{self, File};10use std::io::{self, Cursor, Read, Write};11use std::iter;12use std::os::unix::prelude::PermissionsExt;13use std::path::Path;14use std::str::{from_utf8, FromStr};15use std::{collections::HashMap, path::PathBuf};16use tracing::{error, info, warn};17use tracing_subscriber::filter::LevelFilter;18use tracing_subscriber::EnvFilter;1920#[derive(Clone, Debug)]21struct SecretWrapper(Vec<u8>);22impl Display for SecretWrapper {23 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {24 let encoded = z85::encode(&self.0);25 write!(f, "{encoded}")26 }27}28impl FromStr for SecretWrapper {29 type Err = z85::DecodeError;3031 fn from_str(s: &str) -> Result<Self, Self::Err> {32 z85::decode(s).map(Self)33 }34}35impl<'de> Deserialize<'de> for SecretWrapper {36 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>37 where38 D: Deserializer<'de>,39 {40 let v = String::deserialize(deserializer)?;41 let de = z85::decode(v).map_err(|err| serde::de::Error::custom(err.to_string()))?;42 Ok(Self(de))43 }44}4546#[derive(Parser)]47#[clap(author)]48enum Opts {49 /// Install secrets from json specification50 Install { data: PathBuf },51 /// Reencrypt secret using host key, outputting in z85 encoded string52 Reencrypt {53 #[clap(long)]54 secret: SecretWrapper,55 #[clap(long)]56 targets: Vec<String>,57 },58 /// Decrypt secret using host key, outputting in z85 encoded string59 Decrypt {60 #[clap(long)]61 secret: SecretWrapper,62 /// Shoult decoded output be printed as plaintext, instead of z85?63 #[clap(long)]64 plaintext: bool,65 },66}6768#[derive(Deserialize)]69#[serde(rename_all = "camelCase")]70struct DataItem {71 group: String,72 mode: String,73 owner: String,7475 secret: Option<SecretWrapper>,76 public: Option<String>,7778 public_path: PathBuf,79 stable_public_path: PathBuf,8081 secret_path: PathBuf,82 stable_secret_path: PathBuf,83}8485type Data = HashMap<String, DataItem>;8687fn decrypt(input: &SecretWrapper, identity: &dyn Identity) -> Result<Vec<u8>> {88 let mut input = Cursor::new(&input.0);89 let decryptor = Decryptor::new(&mut input).context("failed to init decryptor")?;90 let decryptor = match decryptor {91 Decryptor::Recipients(r) => r,92 Decryptor::Passphrase(_) => bail!("should be recipients"),93 };94 let mut decryptor = decryptor95 .decrypt(iter::once(identity as &dyn age::Identity))96 .context("failed to decrypt, wrong key?")?;9798 let mut decrypted = Vec::new();99 decryptor100 .read_to_end(&mut decrypted)101 .context("failed to decrypt")?;102 Ok(decrypted)103}104fn encrypt(input: &[u8], targets: Vec<String>) -> Result<SecretWrapper> {105 let recipients = targets106 .into_iter()107 .map(|t| {108 SshRecipient::from_str(&t).map_err(|e| anyhow!("failed to parse recipient: {e:?}"))109 })110 .collect::<Result<Vec<SshRecipient>>>()?;111 let recipients = recipients112 .into_iter()113 .map(|v| Box::new(v) as Box<dyn Recipient + Send>)114 .collect::<Vec<_>>();115 let mut encrypted = vec![];116 let mut encryptor = Encryptor::with_recipients(recipients)117 .expect("recipients provided")118 .wrap_output(&mut encrypted)119 .expect("constructor should not fail");120 io::copy(&mut Cursor::new(input), &mut encryptor).expect("copy should not fail");121 encryptor.finish().context("failed to finish encryption")?;122 Ok(SecretWrapper(encrypted))123}124125fn init_secret(identity: &age::ssh::Identity, value: DataItem) -> Result<()> {126 if let Some(public) = &value.public {127 let mut hashed = File::create(&value.public_path)?;128 let stable_dir = value.stable_public_path.parent().expect("not root");129 let mut stable_temp =130 tempfile::NamedTempFile::new_in(stable_dir).context("failed to create tempfile")?;131 hashed.write_all(public.as_bytes())?;132 stable_temp.write_all(public.as_bytes())?;133 stable_temp.flush()?;134 fs::set_permissions(stable_temp.path(), fs::Permissions::from_mode(0o444))135 .context("perm")?;136 fs::set_permissions(&value.public_path, fs::Permissions::from_mode(0o444))137 .context("perm")?;138139 stable_temp140 .persist(value.stable_public_path)141 .context("failed to persist")?;142 }143 if value.secret.is_none() {144 info!("no secret data found");145 return Ok(());146 }147 let secret = value.secret.as_ref().unwrap();148149 let mode = Mode::from_bits(150 u32::from_str_radix(&value.mode, 8).context("failed to parse mode as octal")?,151 )152 .context("failed to parse mode")?;153 let user = User::from_name(&value.owner)154 .context("failed to get user")?155 .ok_or_else(|| anyhow!("user not found"))?;156 let group = Group::from_name(&value.group)157 .context("failed to get group")?158 .ok_or_else(|| anyhow!("group not found"))?;159160 let stable_dir = value.stable_secret_path.parent().expect("not root");161 let mut stable_temp =162 tempfile::NamedTempFile::new_in(stable_dir).context("failed to create tempfile")?;163 let mut hashed = File::create(&value.secret_path)?;164165 // File is owned by root, and only root can modify it166 let decrypted = decrypt(secret, identity)?;167 if decrypted.is_empty() {168 warn!("secret is decoded as empty, something is broken?");169 }170171 io::copy(&mut Cursor::new(&decrypted), &mut stable_temp)172 .context("failed to write decrypted file")?;173 io::copy(&mut Cursor::new(decrypted), &mut hashed).context("failed to write decrypted file")?;174175 // Make file owned by specified user and group, then change mode176 chown(stable_temp.path(), Some(user.uid), Some(group.gid))177 .context("failed to apply user/group")?;178 chown(&value.secret_path, Some(user.uid), Some(group.gid))179 .context("failed to apply user/group")?;180 fs::set_permissions(stable_temp.path(), fs::Permissions::from_mode(mode.bits())).unwrap();181 fs::set_permissions(&value.secret_path, fs::Permissions::from_mode(mode.bits())).unwrap();182 stable_temp183 .persist(value.stable_secret_path)184 .context("failed to persist")?;185186 Ok(())187}188189fn host_identity() -> anyhow::Result<SshIdentity> {190 let identity = SshIdentity::from_buffer(191 &mut Cursor::new(192 fs::read("/etc/ssh/ssh_host_ed25519_key").context("failed to read host private key")?,193 ),194 None,195 )196 .context("failed to parse identity")?;197 Ok(identity)198}199200fn install(data: &Path) -> anyhow::Result<()> {201 let data = fs::read(data).context("failed to read secrets data")?;202 let data_str = from_utf8(&data).context("failed to read data to string")?;203 let data: Data = serde_json::from_str(data_str).context("failed to parse data")?;204205 if !fs::metadata("/run/secrets")206 .map(|m| m.is_dir())207 .unwrap_or(false)208 {209 fs::create_dir("/run/secrets").context("failed to create secrets directory")?;210 }211212 let identity = host_identity()?;213214 let mut failed = false;215 for (name, value) in data {216 info!("initializing secret {name}");217 if let Err(e) = init_secret(&identity, value) {218 error!(219 "{:?}",220 e.context(format!("failed to initialize secret {}", name))221 );222 failed = true;223 }224 }225 if failed {226 bail!("one or more secrets failed");227 }228229 Ok(())230}231232fn main() -> anyhow::Result<()> {233 tracing_subscriber::fmt()234 .with_env_filter(235 EnvFilter::builder()236 .with_default_directive(LevelFilter::INFO.into())237 .from_env_lossy(),238 )239 .without_time()240 .init();241242 let opts = Opts::parse();243244 match opts {245 Opts::Install { data } => install(&data),246 Opts::Reencrypt { secret, targets } => {247 let identity = host_identity()?;248 let decrypted = decrypt(&secret, &identity).context("during decryption")?;249 let encrypted = encrypt(&decrypted, targets).context("during re-encryption")?;250251 println!("{encrypted}");252 Ok(())253 }254 Opts::Decrypt { secret, plaintext } => {255 let identity = host_identity()?;256 let decrypted = decrypt(&secret, &identity).context("during decryption")?;257258 if plaintext {259 let s = String::from_utf8(decrypted).context("output is not utf8")?;260 print!("{s}");261 } else {262 println!("{}", SecretWrapper(decrypted));263 }264 Ok(())265 }266 }267}crates/better-command/Cargo.tomldiffbeforeafterboth--- a/crates/better-command/Cargo.toml
+++ b/crates/better-command/Cargo.toml
@@ -3,12 +3,10 @@
version = "0.1.0"
edition = "2021"
-# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
-
[dependencies]
-once_cell = "1.19.0"
-regex = "1.10.2"
-serde = { version = "1.0.193", features = ["derive"] }
-serde_json = "1.0.108"
-tracing = "0.1.40"
-tracing-indicatif = "0.3.6"
+once_cell = "1.19"
+regex = "1.10"
+serde = { version = "1.0", features = ["derive"] }
+serde_json = "1.0"
+tracing = "0.1"
+tracing-indicatif = "0.3"
crates/nixlike/Cargo.tomldiffbeforeafterboth--- a/crates/nixlike/Cargo.toml
+++ b/crates/nixlike/Cargo.toml
@@ -7,8 +7,8 @@
alejandra = {git = "https://github.com/kamadorueda/alejandra"}
linked-hash-map = "0.5.6"
peg = "0.8.2"
-serde = "1.0.190"
-thiserror = "1.0.50"
-serde_json = "1.0.107"
+serde = "1.0.196"
+thiserror = "1.0.57"
+serde_json = "1.0.113"
ron = "0.8.1"
serde-transcode = "1.1.1"
flake.lockdiffbeforeafterboth--- a/flake.lock
+++ b/flake.lock
@@ -5,11 +5,11 @@
"systems": "systems"
},
"locked": {
- "lastModified": 1701680307,
- "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
+ "lastModified": 1705309234,
+ "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
"owner": "numtide",
"repo": "flake-utils",
- "rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
+ "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
"type": "github"
},
"original": {
@@ -23,11 +23,11 @@
"systems": "systems_2"
},
"locked": {
- "lastModified": 1681202837,
- "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
+ "lastModified": 1705309234,
+ "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
"owner": "numtide",
"repo": "flake-utils",
- "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
+ "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
"type": "github"
},
"original": {
@@ -38,11 +38,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1704409229,
- "narHash": "sha256-Vc41cRJ3trOnocovLe0zZE35pK5Lfuo/zHk0xx3CNDY=",
+ "lastModified": 1708177587,
+ "narHash": "sha256-Tj/YV9kdC+I7V/kjrq3Bdl8z2VIHT5hiAG74s52vLgw=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "786f788914f2a6e94cedf361541894e972b8fd23",
+ "rev": "3c43b81701e73452df1c080b05770407da9e16d6",
"type": "github"
},
"original": {
@@ -67,11 +67,11 @@
]
},
"locked": {
- "lastModified": 1704075545,
- "narHash": "sha256-L3zgOuVKhPjKsVLc3yTm2YJ6+BATyZBury7wnhyc8QU=",
+ "lastModified": 1708135817,
+ "narHash": "sha256-EUMO/K3+Wgh0THOLoRXhxrh6G/pQ7BlJ8No+ciy1nKA=",
"owner": "oxalica",
"repo": "rust-overlay",
- "rev": "a0df72e106322b67e9c6e591fe870380bd0da0d5",
+ "rev": "c77e68d33a84ce3f9e86905c0f2ef78d5defad28",
"type": "github"
},
"original": {
flake.nixdiffbeforeafterboth--- a/flake.nix
+++ b/flake.nix
@@ -29,7 +29,7 @@
llvmPkgs = pkgs.buildPackages.llvmPackages_11;
rust =
(pkgs.rustChannelOf {
- date = "2024-01-01";
+ date = "2024-02-10";
channel = "nightly";
})
.default
@@ -38,12 +38,14 @@
packages = (import ./pkgs) pkgs pkgs;
devShell = (pkgs.mkShell.override {stdenv = llvmPkgs.stdenv;}) {
nativeBuildInputs = with pkgs; [
+ alejandra
rust
lld
cargo-edit
cargo-udeps
cargo-fuzz
cargo-watch
+ cargo-outdated
pkg-config
openssl
modules/fleet/secrets.nixdiffbeforeafterboth--- a/modules/fleet/secrets.nix
+++ b/modules/fleet/secrets.nix
@@ -1,5 +1,11 @@
-{ lib, fleetLib, config, ... }: with lib; with fleetLib;
-let
+{
+ lib,
+ fleetLib,
+ config,
+ ...
+}:
+with lib;
+with fleetLib; let
sharedSecret = with types; ({config, ...}: {
options = {
expectedOwners = mkOption {
@@ -9,13 +15,14 @@
Secrets would be decrypted and stored to /run/secrets/$\{name} on owners
'';
+ default = null;
};
# TODO: Aren't those options may be just desugared to data/expectedData?
regenerateOnOwnerAdded = mkOption {
type = bool;
description = ''
Is this secret owner-dependent, and needs to be regenerated on ownership set change, or it may be just reencrypted.
-
+
You want to have this option set to true, when this secret contains some reference to its owners, i.e x509 SANs.
'';
};
@@ -24,7 +31,7 @@
type = bool;
description = ''
Should this secret be removed on owner removal, or it may be just reencrypted
-
+
Most probably its value should be equal to regenerateOnOwnerAdded, override only if you know what are you doing.
Contrary to regenerateOnOwnerAdded, you may want to set this option to false, when host permissions are revoked
in some other way than by this secret ownership, I.e by firewall/etc.
@@ -55,7 +62,7 @@
Imported from fleet.nix
'';
- default = [ ];
+ default = [];
};
# TODO: Make secret generator generate arbitrary number of secret/public parts?
# Make it generate a folder, where all files except suffixed by .enc are public, and the rest are secret?
@@ -96,43 +103,121 @@
};
};
};
-in
-{
+in {
options = with types; {
sharedSecrets = mkOption {
type = attrsOf (submodule sharedSecret);
- default = { };
+ default = {};
description = "Shared secrets";
};
hostSecrets = mkOption {
type = attrsOf (attrsOf (submodule hostSecret));
- default = { };
+ default = {};
description = "Host secrets. Imported from fleet.nix";
internal = true;
};
};
config = {
- assertions = mapAttrsToList
+ assertions =
+ mapAttrsToList
(name: secret: {
assertion = secret.expectedOwners == null || builtins.sort (a: b: a < b) secret.owners == builtins.sort (a: b: a < b) secret.expectedOwners;
message = "Shared secret ${name} is expected to be encrypted for ${builtins.toJSON secret.expectedOwners}, but it is encrypted for ${builtins.toJSON secret.owners}. Run fleet secrets regenerate to fix";
})
config.sharedSecrets;
hosts = hostsToAttrs (host: {
- modules =
- let
- cleanupSecret = (secretName: v: {
- inherit (v) public secret;
- shared = true;
- });
- in
- [
- {
- secrets = (mapAttrs cleanupSecret
+ modules = let
+ cleanupSecret = secretName: v: {
+ inherit (v) public secret;
+ shared = true;
+ };
+ in [
+ {
+ secrets =
+ (
+ mapAttrs cleanupSecret
(filterAttrs (_: v: builtins.elem host v.owners) config.sharedSecrets)
- ) // (mapAttrs cleanupSecret (config.hostSecrets.${host} or { }));
- }
- ];
+ )
+ // (mapAttrs cleanupSecret (config.hostSecrets.${host} or {}));
+ }
+ ];
});
+ # TODO: Should this attribute be moved to `nixpkgs.overlays`?
+ overlays = [
+ (final: prev: let
+ lib = final.lib;
+ in {
+ mkPassword = {size ? 32}:
+ final.mkSecretGenerator ''
+ ${final.coreutils}/bin/tr -dc 'A-Za-z0-9!?%=' < /dev/random \
+ | ${final.coreutils}/bin/head -c ${toString size} \
+ | encrypt > $out/secret
+ '';
+ mkRsa = {size ? 4096}:
+ final.mkSecretGenerator ''
+ ${final.openssl}/bin/openssl genrsa -out rsa_private.key ${toString size}
+ ${final.openssl}/bin/openssl rsa -in rsa_private.key -pubout -out rsa_public.key
+
+ sudo cat rsa_private.key | encrypt > $out/secret
+ sudo cat rsa_public.key > $out/public
+ '';
+ # TODO: Move to fleet
+ # TODO: Merge both generators to one with consistent options syntax?
+ # Impure generator is built on local machine, then built closure is copied to remote machine,
+ # and then it is ran in inpure context, so that this generator may access HSMs and other things.
+ mkImpureSecretGenerator = generatorText: machine:
+ (prev.writeShellScript "impureGenerator.sh" ''
+ #!/bin/sh
+ set -eu
+
+ # TODO: Provide encryption function as script passed to `callPackage generator {encrypt = ...;}`
+ function encrypt() {
+ eval ${final.rage}/bin/rage $rageArgs
+ }
+
+ created_at=$(date -u +"%Y-%m-%dT%H:%M:%S.%NZ")
+ echo -n $created_at > $out/created_at
+
+ ${generatorText}
+
+ echo -n SUCCESS > $out/marker
+ '')
+ .overrideAttrs (old: {
+ passthru = {
+ generatorKind = "impure";
+ impureOn = machine;
+ };
+ });
+ # TODO: Implement consistent naming
+ # Pure secret generator is supposed to be run entirely by nix, using `__impure` derivation type...
+ # But for now, it is ran the same way as `impureSecretGenerator`, but on the local machine.
+ mkSecretGenerator = generatorText:
+ (prev.writeShellScript "generator.sh" ''
+ #!/bin/sh
+ set -eu
+ # TODO: User should create output directory by themselves.
+ cd $out
+
+ # TODO: Provide encryption function as script passed to `callPackage generator {encrypt = ...;}`
+ function encrypt() {
+ eval ${final.rage}/bin/rage $rageArgs
+ }
+
+ created_at=$(date -u +"%Y-%m-%dT%H:%M:%S.%NZ")
+ echo -n $created_at > $out/created_at
+
+ ${generatorText}
+
+ echo -n SUCCESS > $out/marker
+ '')
+ .overrideAttrs (old: {
+ passthru = {
+ generatorKind = "pure";
+ };
+ # TODO: make nix daemon build secret, not just the script.
+ # __impure = true;
+ });
+ })
+ ];
};
}