diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8d43eaf6..4eedd998 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,7 +46,7 @@ jobs: # Test against the oldest supported version. # Test against beta Rust to get early warning of any problems that might occur with the upcoming Rust release. # Order: oldest Rust to newest Rust. - rust: [1.85.0, stable, beta] + rust: [1.88.0, stable, beta] # Test with no features and all features. args: ["--no-default-features", "--all-features"] @@ -67,7 +67,7 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - rust: [1.85.0, stable, beta] + rust: [1.88.0, stable, beta] features: ["hsm", "hsm,hsm-tests-kmip"] steps: - name: Checkout repository @@ -113,7 +113,7 @@ jobs: runs-on: ubuntu-22.04 strategy: matrix: - rust: [1.85.0, stable, beta] + rust: [1.88.0, stable, beta] features: ["hsm,hsm-tests-pkcs11"] steps: - name: Checkout repository diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fdec0a67..7ea01460 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,12 +36,12 @@ the relevant RFCs, and how they are related. ### Join the Community -We invite you to join the [RPKI mailing -list](https://lists.nlnetlabs.nl/mailman/listinfo/rpki) and/or [Discord -server](https://discord.gg/8dvKB5Ykhy). Please don't open a GitHub issue for a -question. Instead, follow the discussion on the mailing list and Discord and ask -questions there before you start sending patches. We prefer public discussions -over private ones, so everyone in the community can participate and learn. +We invite you to join the [RPKI community](https://community.nlnetlabs.nl) +and/or [Discord server](https://discord.gg/8dvKB5Ykhy). Please don't open a +GitHub issue for a question. Instead, follow the discussion on the mailing list +and Discord and ask questions there before you start sending patches. We prefer +public discussions over private ones, so everyone in the community can +participate and learn. ### License and copyright @@ -71,10 +71,7 @@ for Krill. This documentation is edited via text files in the [reStructuredText](http://www.sphinx-doc.org/en/stable/rest.html) markup language and then compiled into a static website/offline document using the open source [Sphinx](http://www.sphinx-doc.org) and -[ReadTheDocs](https://readthedocs.org/) tools. You can contribute to the -Krill user manual by sending patches via pull requests on the -[krill-manual](https://github.com/NLnetLabs/krill-manual) GitHub -source repository. +[ReadTheDocs](https://readthedocs.org/) tools. You can contribute to the [man page](https://github.com/NLnetLabs/krill/blob/main/doc/krill.1) by @@ -82,6 +79,9 @@ sending nroff formatted patches. ## Sharing Your Changes +Please contact us before you start coding. One-line fixes are generally fine, +but for new features and rewrites we want to be in the loop from the start. + We would like you to submit a [pull request on GitHub](https://github.com/NLnetLabs/krill/pulls). Please note that you can create a draft pull request to indicate that you're still working on something diff --git a/Cargo.lock b/Cargo.lock index 614cf204..f23026f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -118,6 +118,28 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "aws-lc-rs" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9a7b350e3bb1767102698302bc37256cbd48422809984b98d292c40e2579aa9" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.37.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b092fe214090261288111db7a2b2c2118e5a7f30dc2569f1732c4069a6840549" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", +] + [[package]] name = "backoff" version = "0.4.0" @@ -189,12 +211,6 @@ version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - [[package]] name = "bitflags" version = "2.11.0" @@ -229,9 +245,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aebf35691d1bfb0ac386a69bac2fde4dd276fb618cf8bf4f5318fe285e821bb2" dependencies = [ "find-msvc-tools", + "jobserver", + "libc", "shlex", ] +[[package]] +name = "cesu8" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" + [[package]] name = "cfg-if" version = "1.0.4" @@ -244,6 +268,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "chacha20" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f8d983286843e49675a4b7a2d174efe136dc93a18d69130dd18198a6c167601" +dependencies = [ + "cfg-if", + "cpufeatures 0.3.0", + "rand_core 0.10.0", +] + [[package]] name = "chrono" version = "0.4.44" @@ -309,12 +344,31 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3a822ea5bc7590f9d40f1ba12c0dc3c2760f3482c6984db1573ad11031420831" +[[package]] +name = "cmake" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75443c44cd6b379beb8c5b45d85d0773baf31cce901fe7bb252f4eff3008ef7d" +dependencies = [ + "cc", +] + [[package]] name = "colorchoice" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "const-oid" version = "0.9.6" @@ -365,6 +419,15 @@ dependencies = [ "libc", ] +[[package]] +name = "cpufeatures" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +dependencies = [ + "libc", +] + [[package]] name = "crc32fast" version = "1.5.0" @@ -404,23 +467,22 @@ dependencies = [ [[package]] name = "cryptoki" -version = "0.10.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "781357a7779a8e92ea985121bbf379a9adf0777f44ab6392efc6abd5aa9b67db" +checksum = "ff765b99fc49f3116c9a908484486a2b92fd73c48da45c3a69716471c6cc56c6" dependencies = [ - "bitflags 1.3.2", + "bitflags", "cryptoki-sys", "libloading", "log", - "paste", "secrecy", ] [[package]] name = "cryptoki-sys" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "753e27d860277930ae9f394c119c8c70303236aab0ffab1d51f3d207dbb2bc4b" +checksum = "f1fd850498411e4057f1cba79e6e2bc7cbe960544c1046ab46d4685c403a1121" dependencies = [ "libloading", ] @@ -432,7 +494,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "curve25519-dalek-derive", "digest", "fiat-crypto", @@ -558,6 +620,12 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "dyn-clone" version = "1.0.20" @@ -793,6 +861,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures-channel" version = "0.3.32" @@ -875,9 +949,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi", "wasip2", + "wasm-bindgen", ] [[package]] @@ -889,6 +965,7 @@ dependencies = [ "cfg-if", "libc", "r-efi", + "rand_core 0.10.0", "wasip2", "wasip3", ] @@ -1080,22 +1157,6 @@ dependencies = [ "tower-service", ] -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - [[package]] name = "hyper-util" version = "0.1.20" @@ -1366,6 +1427,38 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + +[[package]] +name = "jni-sys" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" + +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + [[package]] name = "js-sys" version = "0.3.88" @@ -1440,7 +1533,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "r2d2", - "rand 0.9.2", + "rand 0.10.0", "regex", "reqwest", "rpassword", @@ -1511,9 +1604,9 @@ checksum = "09edd9e8b54e49e587e4f6295a7d29c3ea94d469cb40ab8ca70b288248a81db2" [[package]] name = "libc" -version = "0.2.182" +version = "0.2.180" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6800badb6cb2082ffd7b6a67e6125bb39f18782f793520caee8cb8846be06112" +checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" [[package]] name = "libflate" @@ -1561,16 +1654,16 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d0b95e02c851351f877147b7deea7b1afb1df71b63aa5f8270716e0c5720616" dependencies = [ - "bitflags 2.11.0", + "bitflags", "libc", "redox_syscall 0.7.1", ] [[package]] name = "linux-raw-sys" -version = "0.12.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" +checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "litemap" @@ -1593,6 +1686,12 @@ version = "0.4.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "maybe-async" version = "0.2.10" @@ -1627,23 +1726,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "native-tls" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "new_debug_unreachable" version = "1.0.6" @@ -1652,11 +1734,11 @@ checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" [[package]] name = "nix" -version = "0.30.1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" +checksum = "225e7cfe711e0ba79a68baeddb2982723e4235247aefce1482f2f16c27865b66" dependencies = [ - "bitflags 2.11.0", + "bitflags", "cfg-if", "cfg_aliases", "libc", @@ -1738,7 +1820,7 @@ dependencies = [ "serde_json", "serde_path_to_error", "sha2", - "thiserror", + "thiserror 1.0.69", "url", ] @@ -1781,7 +1863,7 @@ dependencies = [ "serde_with", "sha2", "subtle", - "thiserror", + "thiserror 1.0.69", "url", ] @@ -1791,7 +1873,7 @@ version = "0.10.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08838db121398ad17ab8531ce9de97b244589089e290a384c900cb9ff7434328" dependencies = [ - "bitflags 2.11.0", + "bitflags", "cfg-if", "foreign-types", "libc", @@ -1885,12 +1967,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "paste" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" - [[package]] name = "pbkdf2" version = "0.12.2" @@ -2040,13 +2116,69 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.31.0" +version = "0.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +checksum = "958f21e8e7ceb5a1aa7fa87fab28e7c75976e0bfe7e23ff069e0a260f894067d" dependencies = [ "memchr", ] +[[package]] +name = "quinn" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" +dependencies = [ + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror 2.0.18", + "tokio", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "aws-lc-rs", + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand 0.9.2", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.18", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.60.2", +] + [[package]] name = "quote" version = "1.0.44" @@ -2094,6 +2226,17 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rand" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc266eb313df6c5c09c1c7b1fbe2510961e5bcd3add930c1e31f7ed9da0feff8" +dependencies = [ + "chacha20", + "getrandom 0.4.1", + "rand_core 0.10.0", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -2132,13 +2275,19 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "rand_core" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c8d0fd677905edcbeedbf2edb6494d676f0e98d54d5cf9bda0b061cb8fb8aba" + [[package]] name = "redox_syscall" version = "0.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" dependencies = [ - "bitflags 2.11.0", + "bitflags", ] [[package]] @@ -2147,7 +2296,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35985aa610addc02e24fc232012c86fd11f14111180f902b67e2d5331f8ebf2b" dependencies = [ - "bitflags 2.11.0", + "bitflags", ] [[package]] @@ -2158,7 +2307,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom 0.2.17", "libredox", - "thiserror", + "thiserror 1.0.69", ] [[package]] @@ -2212,9 +2361,9 @@ checksum = "a96887878f22d7bad8a3b6dc5b7440e0ada9a245242924394987b21cf2210a4c" [[package]] name = "reqwest" -version = "0.12.28" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" dependencies = [ "base64 0.22.1", "bytes", @@ -2226,21 +2375,21 @@ dependencies = [ "http-body-util", "hyper", "hyper-rustls", - "hyper-tls", "hyper-util", "js-sys", "log", "mime", - "native-tls", "percent-encoding", "pin-project-lite", + "quinn", + "rustls", "rustls-pki-types", + "rustls-platform-verifier", "serde", "serde_json", - "serde_urlencoded", "sync_wrapper", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower", "tower-http", "tower-service", @@ -2293,9 +2442,9 @@ dependencies = [ [[package]] name = "rpki" -version = "0.18.6" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98a043d99463db58c05283f5ae5d9ced858cc3483011747264e21f50b9201cdd" +checksum = "99010980abb0aee7a5c4b1c04d0f42f74f57ac168adb5d38a99b3517a4d72df9" dependencies = [ "base64 0.22.1", "bcder", @@ -2339,6 +2488,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + [[package]] name = "rustc_version" version = "0.4.1" @@ -2350,11 +2505,11 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.4" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +checksum = "146c9e247ccc180c1f61615433868c99f3de3ae256a30a43b49f67c2d9171f34" dependencies = [ - "bitflags 2.11.0", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -2367,15 +2522,27 @@ version = "0.23.36" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c665f33d38cea657d9614f766881e4d510e0eda4239891eea56b4cadcf01801b" dependencies = [ + "aws-lc-rs", "log", "once_cell", - "ring", "rustls-pki-types", "rustls-webpki", "subtle", "zeroize", ] +[[package]] +name = "rustls-native-certs" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "612460d5f7bea540c490b2b6395d8e34a953e52b491accd6c86c8164c5932a63" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + [[package]] name = "rustls-pemfile" version = "2.2.0" @@ -2391,15 +2558,44 @@ version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be040f8b0a225e40375822a563fa9524378b9d63112f53e19ffff34df5d33fdd" dependencies = [ + "web-time", "zeroize", ] +[[package]] +name = "rustls-platform-verifier" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +dependencies = [ + "core-foundation 0.10.1", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + [[package]] name = "rustls-webpki" version = "0.103.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7df23109aa6c1567d1c575b9952556388da57401e4ace1d15f79eedad0d8f53" dependencies = [ + "aws-lc-rs", "ring", "rustls-pki-types", "untrusted", @@ -2411,12 +2607,6 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" -[[package]] -name = "ryu" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" - [[package]] name = "salsa20" version = "0.10.2" @@ -2510,9 +2700,9 @@ dependencies = [ [[package]] name = "secrecy" -version = "0.8.0" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +checksum = "e891af845473308773346dc847b2c23ee78fe442e0472ac50e22a18a93d3ae5a" dependencies = [ "serde", "zeroize", @@ -2524,7 +2714,7 @@ version = "3.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ - "bitflags 2.11.0", + "bitflags", "core-foundation 0.10.1", "core-foundation-sys", "libc", @@ -2639,18 +2829,6 @@ dependencies = [ "serde_core", ] -[[package]] -name = "serde_urlencoded" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" -dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", -] - [[package]] name = "serde_with" version = "3.16.1" @@ -2689,7 +2867,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ "cfg-if", - "cpufeatures", + "cpufeatures 0.2.17", "digest", ] @@ -2866,7 +3044,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a13f3d0daba03132c0aa9767f98351b3488edc2c100cda2d2ec2b04f3d8d3c8b" dependencies = [ - "bitflags 2.11.0", + "bitflags", "core-foundation 0.9.4", "system-configuration-sys", ] @@ -2941,7 +3119,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", ] [[package]] @@ -2955,6 +3142,17 @@ dependencies = [ "syn 2.0.117", ] +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.117", +] + [[package]] name = "thread_local" version = "1.1.9" @@ -3058,16 +3256,6 @@ dependencies = [ "syn 2.0.117", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.4" @@ -3151,7 +3339,7 @@ version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4e6559d53cc268e5031cd8429d05415bc4cb4aefc4aa5d6cc35fbf5b924a1f8" dependencies = [ - "bitflags 2.11.0", + "bitflags", "bytes", "futures-util", "http", @@ -3429,7 +3617,7 @@ version = "0.244.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47b807c72e1bac69382b3a6fb3dbe8ea4c0ed87ff5629b8685ae6b9a611028fe" dependencies = [ - "bitflags 2.11.0", + "bitflags", "hashbrown 0.15.5", "indexmap 2.13.0", "semver", @@ -3445,6 +3633,25 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-root-certs" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "804f18a4ac2676ffb4e8b5b5fa9ae38af06df08162314f96a68d2a363e21a8ca" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "winapi" version = "0.3.9" @@ -3546,6 +3753,15 @@ dependencies = [ "windows-link", ] +[[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.52.0" @@ -3582,6 +3798,21 @@ dependencies = [ "windows-link", ] +[[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]] name = "windows-targets" version = "0.52.6" @@ -3615,6 +3846,12 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[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" version = "0.52.6" @@ -3627,6 +3864,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[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.52.6" @@ -3639,6 +3882,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[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" version = "0.52.6" @@ -3663,6 +3912,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[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" version = "0.52.6" @@ -3675,6 +3930,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[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" version = "0.52.6" @@ -3687,6 +3948,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[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" version = "0.52.6" @@ -3699,6 +3966,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[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" version = "0.52.6" @@ -3781,7 +4054,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d66ea20e9553b30172b5e831994e35fbde2d165325bec84fc43dbf6f4eb9cb2" dependencies = [ "anyhow", - "bitflags 2.11.0", + "bitflags", "indexmap 2.13.0", "log", "serde", diff --git a/Cargo.toml b/Cargo.toml index 21364495..9e8761d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "krill" version = "0.15.1-dev" edition = "2024" -rust-version = "1.85" +rust-version = "1.88" authors = ["NLnet Labs "] description = "Resource Public Key Infrastructure (RPKI) daemon" homepage = "https://www.nlnetlabs.nl/projects/routing/krill/" @@ -40,26 +40,26 @@ log = "0.4" openssl = { version = "0.10", features = ["v110"] } percent-encoding = "2.3.1" pin-project-lite = "0.2.16" -rand = "0.9" +rand = "0.10" regex = { version = "1.11.1", default-features = false, features = [ "std" ] } -reqwest = { version = "0.12.23", features = ["json"] } -rpki = { version = "0.18.6", features = ["ca", "compat", "rrdp"] } +reqwest = { version = "0.13.2", features = ["json"] } +rpki = { version = "0.19.2", features = ["ca", "compat", "rrdp"] } rustls-pemfile = "2.2.0" serde = { version = "1.0", features = ["derive", "rc"] } serde_json = "1.0" tempfile = "3.19.1" tokio = { version = "1", features = [ "macros", "rt", "rt-multi-thread", "signal", "time" ] } -tokio-rustls = { version = "0.26", default-features = false, features = [ "ring", "logging", "tls12" ] } +tokio-rustls = { version = "0.26" } toml = "0.9.5" url = { version = "2.5.4", features = ["serde"] } uuid = { version = "1.16", features = ["serde", "v4"] } # Dependencies used by the "hsm" feature backoff = { version = "0.4.0", optional = true } -cryptoki = { version = "0.10", optional = true } +cryptoki = { version = "0.12", optional = true, features = [ "serde" ] } kmip = { version = "0.4.3", package = "kmip-protocol", features = [ "tls-with-openssl" ], optional = true } r2d2 = { version = "0.8.10", optional = true } -secrecy = { version = "0.8", features = ["serde"], optional = true } +secrecy = { version = "0.10.3", features = ["serde"], optional = true } # Dependencies used by the "multi-user" feature basic-cookies = { version = "0.1", optional = true } @@ -78,7 +78,7 @@ urlparse = { version = "0.7", optional = true } [target.'cfg(unix)'.dependencies] syslog = "7.0.0" -nix = { version = "0.30.1", features = ["user"] } +nix = { version = "0.31.1", features = ["user"] } [features] default = ["multi-user", "hsm"] @@ -102,7 +102,6 @@ hsm-tests-pkcs11 = ["hsm"] [dev-dependencies] tar = "0.4" stderrlog = "0.6" -tempfile = "3.19.1" urlparse = "0.7" # Make sure that Krill crashes on panics, rather than losing threads and diff --git a/Changelog.md b/Changelog.md index 39947ea6..9b13beea 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,6 +1,15 @@ # Change Log -## Unreleased Next Version +## Unreleased next version + +Bug fixes + +Other changes + + +## 0.16.1-rc1 + +Released 2026-02-19. Breaking changes @@ -12,6 +21,8 @@ Breaking changes fields and added `bgp_riswhois_enabled`, `bgp_riswhois_v4_uri`, `bgp_riswhois_v6_uri`, and `bgp_riswhois_refresh_duration` fields, all of which are optional. ([#1329] +* Krill will now refuse to start if the config file contains unknown + options. ([#1322]) New @@ -20,6 +31,9 @@ New By default, only the `root` user is allowed with the `admin` role, but both allowed users and what role they are mapped to can be configure. ([#1322]) +* Added a `krillc parents refresh` command to allow refreshing the parents + of a single CA rather than having to do a bulk refresh which can take a + very long time if there are many CAs. ([#1353]) Bug fixes @@ -33,18 +47,51 @@ Bug fixes * Start sweeping the authenticator cache upon daemon startup. This merely reduces memory consumption of the cache. Expired authentication tokens were not used either way. ([#1337]) +* Fixed a bug introduced in 0.15.0 where CAs do to not clear fulfilled + certification requests causing them to re-request a certificate every + time they contact their parent. ([#1345]) +* Do not re-try syncing with a parent of a CA when that parent isn’t + known. ([#1349]) +* Fixed un-suspending child CAs: rather then re-publishing the previously + revoked certificate, a new certificate is now issued. ([#1341]) Other changes * The default config files don’t serve as config documentation any more. Rather, there is now a `krill.conf.5` manual page. This manual page is also included in the Krill manual. ([#1322]) +* The cryptography library used by the rustls TLS implementation has been + switched to aws-lc-rs. This has some consequences for packaging: +* Dropped packaging for Ubuntu 20.04 (Focal Fossa). ([#1359]) [#1322]: https://github.com/NLnetLabs/krill/pull/1322 [#1326]: https://github.com/NLnetLabs/krill/pull/1326 [#1329]: https://github.com/NLnetLabs/krill/pull/1329 [#1331]: https://github.com/NLnetLabs/krill/pull/1331 [#1337]: https://github.com/NLnetLabs/krill/pull/1337 +[#1341]: https://github.com/NLnetLabs/krill/pull/1341 +[#1344]: https://github.com/NLnetLabs/krill/pull/1344 +[#1349]: https://github.com/NLnetLabs/krill/pull/1349 +[#1353]: https://github.com/NLnetLabs/krill/pull/1353 +[#1359]: https://github.com/NLnetLabs/krill/pull/1359 + + +## 0.15.1 ‘Contains Adult Language’ + +Released 2026-01-19. + +Bug fixes + +* Fixed a bug introduced in 0.15.0 where CAs do to not clear fulfilled + certification requests causing them to re-request a certificate every + time they contact their parent. ([#1345]) + +Other changes + +* Updated dependencies. + +[#1345]: https://github.com/NLnetLabs/krill/pull/1345 +[#1346]: https://github.com/NLnetLabs/krill/pull/1346 ## 0.15.0 ‘But I Digress’ diff --git a/Dockerfile b/Dockerfile index 2729fc68..f53f9170 100644 --- a/Dockerfile +++ b/Dockerfile @@ -44,7 +44,7 @@ ARG MODE=build # ======== # # Only used when MODE=build. -ARG BASE_IMG=alpine:3.22 +ARG BASE_IMG=alpine:3.23 # CARGO_ARGS diff --git a/doc/manual/source/man/krillc.rst b/doc/manual/source/man/krillc.rst index ac7b200a..de46050b 100644 --- a/doc/manual/source/man/krillc.rst +++ b/doc/manual/source/man/krillc.rst @@ -342,6 +342,17 @@ Manage parents for a CA .. option:: -r , --response= Path to the RFC 8183 Child Request XML file + + .. subcmd:: refresh + + Refresh the parents of this CA + + + *OPTIONS* + + .. option:: -c , --ca= [env: KRILL_CLI_MY_CA] + + Name of the CA to control .. subcmd:: contact diff --git a/doc/manual/source/trust-anchor.rst b/doc/manual/source/trust-anchor.rst index 659a2531..865c6c7d 100644 --- a/doc/manual/source/trust-anchor.rst +++ b/doc/manual/source/trust-anchor.rst @@ -377,6 +377,13 @@ endpoints for the TA certificate. --tal-rsync +.. code-block:: bash + + krillta signer init --proxy-id ./proxy-id.json \ + --proxy-repository-contact ./proxy-repo.json \ + --tal-https https://krillrepo.example.com/ta/ta.cer \ + --tal-rsync rsync://krillrepo.example.com/ta/ta.cer + Associate the TA Signer with the Proxy -------------------------------------- @@ -384,7 +391,7 @@ Get the TA Signer 'info' JSON file and save it: .. code-block:: bash - krillta signer show > ./signer-info.json + krillta signer --format json show > ./signer-info.json Then 'initialise' the signer associated with the TA Proxy. (we should @@ -423,9 +430,15 @@ Step 2: Add "online" as a child of "ta" .. code-block:: bash - krillc show --ca online --format json >./online.json + krillc --format json show --ca online >./online.json krillta proxy children add --info ./online.json >./res.xml +.. Note:: You can specify the address space (ASNs, IPv4, IPv6) covered by + your child CA using the followings parameters: + - ``--asn`` The ASN resources for the child [default: AS0-AS4294967295] + - ``--ipv4`` The IPv4 resources for the child [default: 0.0.0.0/0] + - ``--ipv6`` The IPv6 resources for the child [default: ::/0] + Step 3: Add "ta" as a parent of "online" .. code-block:: bash @@ -512,7 +525,7 @@ Save the TA Signer Response .. code-block:: bash - krillta signer last > ./response.json + krillta signer --format json last > ./response.json Upload the Signer Response diff --git a/src/api/ca.rs b/src/api/ca.rs index b35b8607..33ac0682 100644 --- a/src/api/ca.rs +++ b/src/api/ca.rs @@ -279,7 +279,7 @@ pub struct CertInfo { /// The serial number of this certificate. /// - /// This is needed for revocatio. + /// This is needed for revocation. pub serial: Serial, /// The certifcate signing request for the certificate. @@ -1532,10 +1532,11 @@ impl ChildExchange { if agent == "local-child" { return true; } - else if let Some(version) = agent.strip_prefix("krill/") { - if let Ok(krill_version) = KrillVersion::from_str(version) { - return krill_version > KrillVersion::release(0, 9, 1); - } + else if + let Some(version) = agent.strip_prefix("krill/") + && let Ok(krill_version) = KrillVersion::from_str(version) + { + return krill_version > KrillVersion::release(0, 9, 1); } } false @@ -1900,22 +1901,22 @@ impl fmt::Display for ResourceClassKeysInfo { write!(f, "State: ")?; match &self { - ResourceClassKeysInfo::Pending(_) => write!(f, "pending")?, - ResourceClassKeysInfo::Active(_) => write!(f, "active")?, + ResourceClassKeysInfo::Pending(_) => writeln!(f, "pending")?, + ResourceClassKeysInfo::Active(_) => writeln!(f, "active")?, ResourceClassKeysInfo::RollPending(_) => { - write!(f, "roll phase 1: pending and active key")? + writeln!(f, "roll phase 1: pending and active key")? } ResourceClassKeysInfo::RollNew(_) => { - write!(f, "roll phase 2: new and active key")? + writeln!(f, "roll phase 2: new and active key")? } ResourceClassKeysInfo::RollOld(_) => { - write!(f, "roll phase 3: active and old key")? + writeln!(f, "roll phase 3: active and old key")? } } if let Some(key) = self.current_key() { let resources = &key.incoming_cert.resources; - writeln!(f, " Resources:")?; + writeln!(f, "Resources:")?; writeln!(f, " ASNs: {}", resources.asn())?; writeln!(f, " IPv4: {}", resources.ipv4())?; writeln!(f, " IPv6: {}", resources.ipv6())?; diff --git a/src/cli/client.rs b/src/cli/client.rs index 703fc2c0..7fbd6e0e 100644 --- a/src/cli/client.rs +++ b/src/cli/client.rs @@ -538,6 +538,14 @@ impl KrillClient { ).await } + pub async fn parent_refresh( + &self, ca: &CaHandle, + ) -> Result { + self.post_empty( + ca_path(ca).into_iter().chain(once("sync/parents")), + ).await + } + pub async fn parent_details( &self, ca: &CaHandle, parent: &ParentHandle ) -> Result { @@ -1120,10 +1128,11 @@ impl TryFrom for ServerUri { } // Check for a five-character scheme. - if let Some(scheme) = value.as_bytes().get(0..8) { - if scheme.eq_ignore_ascii_case(b"https://") { - return Ok(Self::Http(value)) - } + if + let Some(scheme) = value.as_bytes().get(0..8) + && scheme.eq_ignore_ascii_case(b"https://") + { + return Ok(Self::Http(value)) } Err("unsupported URI scheme") diff --git a/src/cli/options/parents.rs b/src/cli/options/parents.rs index e72593fb..6c559306 100644 --- a/src/cli/options/parents.rs +++ b/src/cli/options/parents.rs @@ -23,6 +23,9 @@ pub enum Command { /// Add a parent to, or update a parent of a CA Add(Add), + /// Refresh the parents of this CA + Refresh(Refresh), + /// Show contact information for a parent of a CA Contact(CaContact), @@ -38,6 +41,7 @@ impl Command { match self { Self::Request(cmd) => cmd.run(client).await.into(), Self::Add(cmd) => cmd.run(client).await.into(), + Self::Refresh(cmd) => cmd.run(client).await.into(), Self::Contact(cmd) => cmd.run(client).await.into(), Self::Statuses(cmd) => cmd.run(client).await.into(), Self::Remove(cmd) => cmd.run(client).await.into(), @@ -104,6 +108,25 @@ impl Add { } +//------------ Refresh ------------------------------------------------------- + +#[derive(clap::Parser)] +pub struct Refresh { + #[command(flatten)] + ca: ca::Handle, +} + +impl Refresh { + pub async fn run( + self, client: &KrillClient + ) -> Result { + client.parent_refresh( + &self.ca.ca, + ).await + } +} + + //------------ CaContact ----------------------------------------------------- #[derive(clap::Args)] diff --git a/src/commons/crypto/signing/dispatch/krillsigner.rs b/src/commons/crypto/signing/dispatch/krillsigner.rs index 4d5a161e..005a1016 100644 --- a/src/commons/crypto/signing/dispatch/krillsigner.rs +++ b/src/commons/crypto/signing/dispatch/krillsigner.rs @@ -368,12 +368,13 @@ impl KrillSigner { pub fn sign_rta( &self, rta_builder: &mut rta::RtaBuilder, + signing_time: Time, ee: Cert, ) -> CryptoResult<()> { let key = ee.subject_key_identifier(); rta_builder.push_cert(ee); rta_builder - .sign(&self.router, &key, None, None) + .sign(&self.router, &key, signing_time) .map_err(crypto::Error::signing) } diff --git a/src/commons/crypto/signing/signers/pkcs11/context.rs b/src/commons/crypto/signing/signers/pkcs11/context.rs index 6ee459d1..3869dbdf 100644 --- a/src/commons/crypto/signing/signers/pkcs11/context.rs +++ b/src/commons/crypto/signing/signers/pkcs11/context.rs @@ -28,7 +28,7 @@ use std::sync::OnceLock; use cryptoki::error::Error as Pkcs11Error; use cryptoki::{ - context::{CInitializeArgs, Info, Pkcs11}, + context::{CInitializeArgs, CInitializeFlags, Info, Pkcs11}, mechanism::Mechanism, object::{Attribute, AttributeType, ObjectHandle}, session::{Session, UserType}, @@ -166,7 +166,9 @@ impl Pkcs11Context { // this way of configuring the PKCS#11 token. // TODO: add a timeout around the call to initialize? - if let Err(err) = self.initialize(CInitializeArgs::OsThreads) { + if let Err(err) = self.initialize( + CInitializeArgs::new(CInitializeFlags::OS_LOCKING_OK) + ) { error!( "Failed to initialize PKCS#11 library '{}': {}", self.lib_file_name, err @@ -188,7 +190,12 @@ impl Pkcs11Context { self.initialized = false; // will continue even if the call fails. - self.finalize(); + if let Err(err) = self.finalize() { + error!( + "Error uninitializing PKCS#11 library '{}': {}", + self.lib_file_name, err + ); + } // remove the library we represent from the initialized set (as it // is no longer initialized), subsequent attempts to use the @@ -231,12 +238,13 @@ impl Pkcs11Context { res } - fn logged_cryptoki_call_with_take( + fn logged_cryptoki_call_with_take( &mut self, cryptoki_call_name: &'static str, call: F, - ) where - F: FnOnce(Pkcs11), + ) -> Result + where + F: FnOnce(Pkcs11) -> Result, { trace!("{}::{}()", self.lib_file_name, cryptoki_call_name); let ctx = self.ctx.take().unwrap(); // leave a None in the ctx member field @@ -254,7 +262,7 @@ impl Pkcs11Context { }) } - fn finalize(&mut self) { + fn finalize(&mut self) -> Result<(), Pkcs11Error>{ self.logged_cryptoki_call_with_take("Finalize", |cryptoki| { cryptoki.finalize() }) diff --git a/src/commons/crypto/signing/signers/pkcs11/signer.rs b/src/commons/crypto/signing/signers/pkcs11/signer.rs index 5a128844..6486838e 100644 --- a/src/commons/crypto/signing/signers/pkcs11/signer.rs +++ b/src/commons/crypto/signing/signers/pkcs11/signer.rs @@ -1389,9 +1389,9 @@ fn is_transient_error(err: &Pkcs11Error) -> bool { | Pkcs11Error::ParseInt(_) | Pkcs11Error::Utf8(_) | Pkcs11Error::NulError(_) + | Pkcs11Error::MissingSymbol(_) | Pkcs11Error::InvalidValue - | Pkcs11Error::PinNotSet - | Pkcs11Error::AlreadyInitialized => { + | Pkcs11Error::PinNotSet => { // The Rust `pkcs11` crate had a serious problem such as the // loaded library not exporting a required function or // that it was asked to initialize an already initialized library. @@ -1512,6 +1512,7 @@ fn is_transient_error(err: &Pkcs11Error) -> bool { cryptoki::error::RvError::TokenNotPresent => true, /* not present at the time the function was executed but might be later */ cryptoki::error::RvError::TokenNotRecognized => false, cryptoki::error::RvError::TokenWriteProtected => true, /* maybe the write protection is a transient condition? */ + cryptoki::error::RvError::UnknownErrorCode(_) => false, /* we don’t know ... */ cryptoki::error::RvError::UnwrappingKeyHandleInvalid => false, cryptoki::error::RvError::UnwrappingKeySizeRange => false, cryptoki::error::RvError::UnwrappingKeyTypeInconsistent => { @@ -1523,7 +1524,7 @@ fn is_transient_error(err: &Pkcs11Error) -> bool { cryptoki::error::RvError::UserPinNotInitialized => true, /* maybe the operator will initialize the PIN */ cryptoki::error::RvError::UserTooManyTypes => true, /* maybe some sessions are terminated while retrying permitting us to succeed? */ cryptoki::error::RvError::UserTypeInvalid => true, /* maybe the operator will fix the users type */ - cryptoki::error::RvError::VendorDefined => true, /* we have no way of knowing what this kind of failure is, maybe it is transient */ + cryptoki::error::RvError::VendorDefined(_) => true, /* we have no way of knowing what this kind of failure is, maybe it is transient */ cryptoki::error::RvError::WrappedKeyInvalid => false, cryptoki::error::RvError::WrappedKeyLenRange => false, cryptoki::error::RvError::WrappingKeyHandleInvalid => false, diff --git a/src/config.rs b/src/config.rs index 10063723..2d9f284c 100644 --- a/src/config.rs +++ b/src/config.rs @@ -10,6 +10,7 @@ use std::{ use chrono::Duration; use log::{error, info, warn, LevelFilter}; +use rand::RngExt; use rpki::{ ca::idexchange::PublisherHandle, repository::x509::{Time, Validity}, @@ -725,7 +726,6 @@ impl IssuanceTimingConfig { let random_mins = if self.timing_publish_next_jitter_hours == 0 { 0 } else { - use rand::Rng; let mut rng = rand::rng(); rng.random_range(0..(60 * self.timing_publish_next_jitter_hours)) } as i64; @@ -1120,7 +1120,6 @@ impl Config { let random_seconds = if jitter_seconds == 0 { 0 } else { - use rand::Rng; let mut rng = rand::rng(); rng.random_range(0..jitter_seconds) }; diff --git a/src/server/bgp/rotoapi.rs b/src/server/bgp/rotoapi.rs deleted file mode 100644 index 9b2e05be..00000000 --- a/src/server/bgp/rotoapi.rs +++ /dev/null @@ -1,1313 +0,0 @@ -//! The BGP analyser. - -use std::time::{Duration, Instant}; -use std::{error, fmt}; -use std::collections::HashMap; -use std::ops::Range; -use std::str::FromStr; -use intervaltree::IntervalTree; -use rpki::repository::resources::{Addr, AddressRange, Prefix, ResourceSet}; -use serde::{Deserialize, Serialize}; -use serde_json::Value; -use tokio::sync::Mutex; -use crate::api::bgp::{ - Announcement, BgpAnalysisEntry, BgpAnalysisReport, BgpAnalysisState, - BgpAnalysisSuggestion, ReplacementRoaSuggestion, -}; -use crate::api::roa::{ - AsNumber, ConfiguredRoa, Ipv4Prefix, Ipv6Prefix, RoaPayload, TypedPrefix, -}; - - -//------------ BgpAnalyser ------------------------------------------------- - -/// The BGP analyser to check the consequence of ROAs in the global BGP. -pub struct BgpAnalyser { - /// Should we actually use the BGP API. - bgp_api_enabled: bool, - - /// The base URI of the BGP API. - bgp_api_uri: String, - - /// The HTTP client to talk to the BGP API with. - client: reqwest::Client, - - /// The cache for the HTTP client responses - cache: Mutex>, - - /// The duration to keep responses cached. - cache_duration: Duration, -} - -impl BgpAnalyser { - /// Creates a new BGP analyser from the BGP API details. - pub fn new( - bgp_api_enabled: bool, - bgp_api_uri: String, - cache_duration: Duration, - ) -> Self { - BgpAnalyser { - bgp_api_enabled, - bgp_api_uri, - client: reqwest::Client::new(), - cache: Mutex::new(HashMap::new()), - cache_duration, - } - } - - /// Creates a BGP analyisis report for the given ROAs and resources. - pub async fn analyse( - &self, - roas: &[ConfiguredRoa], - resources_held: &ResourceSet, - limited_scope: Option, - ) -> BgpAnalysisReport { - let mut entries = Vec::new(); - - // Create a list of the ROAs that are contained in the held - // resources but not in the limited scope. Everything that is in - // neither goes directly into the `entries` as ‘not held.’ - let mut roas_held = Vec::new(); - for roa in roas { - if let Some(limit) = limited_scope.as_ref() { - if !limit.contains_roa_address( - &roa.roa_configuration.payload.as_roa_ip_address() - ) { - continue - } - } - - if resources_held.contains_roa_address( - &roa.roa_configuration.payload.as_roa_ip_address() - ) { - roas_held.push(roa.clone()); - } - else { - entries.push(BgpAnalysisEntry::roa_not_held(roa.clone())); - } - } - - if !self.bgp_api_enabled { - // Nothing to analyse. Push all ROAs as ‘no announcement info.’ - entries.extend( - roas_held.into_iter().map(|roa| { - BgpAnalysisEntry::roa_no_announcement_info(roa) - }) - ); - return BgpAnalysisReport::new(entries); - } - - // Now get all the necessary data from BGP API. - // - // Return early if this failed. - // - // If this succeeds, `scoped_announcements` will contain all - // announcements that overlap any of the IP address resources we - // are considering. - let scope = IpRange::from_resource_set( - match &limited_scope { - Some(limit) => limit, - None => resources_held, - } - ); - - let mut scoped_announcements: Vec = vec![]; - for block in scope.into_iter() { - let announcements = self.retrieve(block).await; - if let Ok(mut announcements) = announcements { - scoped_announcements.append( - announcements.as_mut()); - } - else { - entries.extend( - roas_held.into_iter().map(|roa| { - BgpAnalysisEntry::roa_no_announcement_info(roa) - }) - ); - return BgpAnalysisReport::new(entries); - } - } - - // Now create a prefix tree for all the configured ROAs: `roa_tree`. - let roa_tree = IpRangeStore::create( - roas_held.iter().map(|configured| { - let payload = configured.roa_configuration.payload; - (payload.prefix.into(), payload) - }) - ); - - // Now go over all announcements and determine their ROV status from - // our ROAs. Turn that into a prefix tree: `validated_tree`. - let validated: Vec = scoped_announcements - .into_iter() - .map(|a| roa_tree.validate_announcement(a)) - .collect(); - let validated_tree = IpRangeStore::create( - validated.iter().map(|v| (v.announcement.prefix.into(), v.clone())) - ); - - // Now we go over each individual configured ROA and check how it - // influenced the validated tree. - for roa in roas_held { - // Get all announcements covered by the ROA. - let covered = validated_tree.matching_or_more_specific( - roa.roa_configuration.payload.prefix - ); - - // Get all other ROAs that cover the prefix of this ROA. - let other_roas_covering_this_prefix: Vec<_> = roa_tree - .matching_or_less_specific( - roa.roa_configuration.payload.prefix - ) - .into_iter() - .filter(|other| roa.roa_configuration.payload != **other) - .cloned() - .collect(); - - // Get all ROAs that include this ROA. - let other_roas_including_this_definition: Vec<_> = - other_roas_covering_this_prefix - .iter() - .filter(|other| { - other.asn == roa.roa_configuration.payload.asn - && other.prefix.addr_len() - <= roa.roa_configuration.payload - .prefix.addr_len() - && other.effective_max_length() - >= roa.roa_configuration.payload - .effective_max_length() - }) - .cloned() - .collect(); - - let authorizes: Vec = covered - .iter() - .filter(|va| { - // VALID announcements under THIS ROA - // Already covered so it's under this ROA prefix - // ASN must match - // Prefix length must be allowed under this ROA (it - // could be allowed by another ROA and therefore - // valid) - va.validity == AnnouncementValidity::Valid - && va.announcement.prefix.addr_len() - <= roa.roa_configuration.payload - .effective_max_length() - && va.announcement.asn - == roa.roa_configuration.payload.asn - }) - .map(|va| va.announcement) - .collect(); - - let disallows: Vec = covered - .iter() - .filter(|va| { - let validity = va.validity; - validity == AnnouncementValidity::InvalidLength - || validity == AnnouncementValidity::InvalidAsn - }) - .map(|va| va.announcement) - .collect(); - - let authorizes_excess = { - let max_length = - roa.roa_configuration.payload.effective_max_length(); - let nr_of_specific_ann = authorizes - .iter() - .filter(|ann| ann.prefix.addr_len() == max_length) - .count() - as u128; - - nr_of_specific_ann > 0 - && nr_of_specific_ann - < roa.roa_configuration.payload - .nr_of_specific_prefixes() - }; - - if roa.roa_configuration.payload.asn == AsNumber::AS0 { - // see if this AS0 ROA is redundant, if it is mark it as - // such - if other_roas_covering_this_prefix.is_empty() { - // will disallow all covered announcements by - // definition (because AS0 announcements cannot exist) - let announcements = covered - .iter() - .map(|va| va.announcement) - .collect(); - entries.push(BgpAnalysisEntry::roa_as0( - roa, - announcements, - )); - } else { - entries.push(BgpAnalysisEntry::roa_as0_redundant( - roa, - other_roas_covering_this_prefix, - )); - } - } else if !other_roas_including_this_definition.is_empty() { - entries.push(BgpAnalysisEntry::roa_redundant( - roa, - authorizes, - disallows, - other_roas_including_this_definition, - )) - } else if authorizes.is_empty() && disallows.is_empty() { - entries.push(BgpAnalysisEntry::roa_unseen(roa)) - } else if authorizes_excess { - entries.push(BgpAnalysisEntry::roa_too_permissive( - roa, authorizes, disallows, - )) - } else if authorizes.is_empty() { - entries.push(BgpAnalysisEntry::roa_disallowing( - roa, disallows, - )) - } else { - entries.push(BgpAnalysisEntry::roa_seen( - roa, authorizes, disallows, - )) - } - } - - // Loop over all validated announcements and report - for v in validated.into_iter() { - match v.validity { - AnnouncementValidity::Valid => { - entries.push(BgpAnalysisEntry::announcement_valid( - v.announcement, - v.authorizing.unwrap(), /* always set for valid - * announcements */ - )) - } - AnnouncementValidity::Disallowed => { - entries.push( - BgpAnalysisEntry::announcement_disallowed( - v.announcement, - v.disallowing, - ), - ); - } - AnnouncementValidity::InvalidLength => { - entries.push( - BgpAnalysisEntry::announcement_invalid_length( - v.announcement, - v.disallowing, - ), - ); - } - AnnouncementValidity::InvalidAsn => { - entries.push( - BgpAnalysisEntry::announcement_invalid_asn( - v.announcement, - v.disallowing, - ), - ); - } - AnnouncementValidity::NotFound => { - entries.push( - BgpAnalysisEntry::announcement_not_found( - v.announcement, - ), - ); - } - } - } - - BgpAnalysisReport::new(entries) - } - - /// Returns suggestions for the given ROAs and resources. - pub async fn suggest( - &self, - roas: &[ConfiguredRoa], - resources_held: &ResourceSet, - limited_scope: Option, - ) -> BgpAnalysisSuggestion { - let mut suggestion = BgpAnalysisSuggestion::default(); - - // perform analysis - let entries = self - .analyse(roas, resources_held, limited_scope) - .await - .into_entries(); - for entry in &entries { - match entry.state() { - BgpAnalysisState::RoaUnseen => { - suggestion.stale.push(entry.configured_roa().clone()) - } - BgpAnalysisState::RoaTooPermissive => { - let replace_with = entry - .authorizes() - .iter() - .filter(|ann| { - !entries.iter().any(|other| { - other != entry - && other.authorizes().contains(*ann) - }) - }) - .map(|auth| RoaPayload::from(*auth)) - .collect(); - - suggestion.too_permissive.push( - ReplacementRoaSuggestion { - current: entry.configured_roa().clone(), - new: replace_with, - } - ); - } - BgpAnalysisState::RoaSeen | BgpAnalysisState::RoaAs0 => { - suggestion.keep.push(entry.configured_roa().clone()) - } - BgpAnalysisState::RoaDisallowing => { - suggestion.disallowing.push(entry.configured_roa().clone()) - } - BgpAnalysisState::RoaRedundant => { - suggestion.redundant.push(entry.configured_roa().clone()) - } - BgpAnalysisState::RoaNotHeld => { - suggestion.not_held.push(entry.configured_roa().clone()) - } - BgpAnalysisState::RoaAs0Redundant => { - suggestion.as0_redundant.push( - entry.configured_roa().clone() - ) - } - BgpAnalysisState::AnnouncementValid => {} - BgpAnalysisState::AnnouncementNotFound => { - suggestion.not_found.push(entry.announcement()) - } - BgpAnalysisState::AnnouncementInvalidAsn => { - suggestion.invalid_asn.push(entry.announcement()) - } - BgpAnalysisState::AnnouncementInvalidLength => { - suggestion.invalid_length.push(entry.announcement()) - } - BgpAnalysisState::AnnouncementDisallowed => { - suggestion.keep_disallowing.push(entry.announcement()) - } - BgpAnalysisState::RoaNoAnnouncementInfo => { - suggestion.keep.push(entry.configured_roa().clone()) - } - } - } - - suggestion - } - - /// Retrieves all announcements overlapping an IP range from BGP API. - async fn retrieve( - &self, - block: IpRange, - ) -> Result, BgpApiError> { - let mut announcements: Vec = vec![]; - - for prefix in block.to_prefixes() { - let resp = self.get_url(self.format_url(prefix)).await?; - match self.obtain_announcements(resp) { - Some(mut ann) => announcements.append(&mut ann), - None => return Err(BgpApiError::MalformedData), - } - } - - Ok(announcements) - } - - /// Formats the URL to retrieve announcements for the given prefix. - fn format_url(&self, prefix: TypedPrefix) -> String { - format!("{}/api/v1/prefix/{:?}/{}/search", - self.bgp_api_uri, prefix.ip_addr(), prefix.addr_len() - ) - } - - /// Fetches the URL and parses the returned JSON. - async fn get_url(&self, url: String) -> Result { - #[cfg(test)] - if url.starts_with("test") { - // When testing, the "test" URL is special. Also, unwrapping is - // fine. - let value = serde_json::from_str::(include_str!( - "../../../test-resources/bgp/bgp-api.json") - ).unwrap(); - let Value::Object(mut value) = value else { - panic!("not an object") - }; - return Ok(value.remove(url.as_str()).unwrap()) - } - - { - let mut local_cache = self.cache.lock().await; - - if let Some((time, value)) = &local_cache.get(&url) { - if time.elapsed() > self.cache_duration { - local_cache.remove(&url); - } else { - return Ok(value.clone()); - } - } - } - - let value: Value = self.client.get( - url.as_str() - ).send().await?.json().await?; - - self.cache.lock().await.insert( - url, (Instant::now(), value.clone()) - ); - Ok(value) - } - - /// Obtain the announcements from the JSON tree. - /// - /// Returns `None` if the JSON structure was in any way unexpected. - fn obtain_announcements(&self, json: Value) -> Option> { - let mut anns: Vec = Vec::new(); - if let Some(result_type) = json.get("result")?.get("type") { - if result_type.as_str()? == "empty-match" { - return Some(anns); - } - } - - let prefix_str = json.get("result")?.get("prefix")?.as_str()?; - for meta in json.get("result")?.get("meta")?.as_array()? { - self.parse_meta(meta, prefix_str, &mut anns)?; - } - if let Some(relations) = json.get("result")?.get("relations") { - for relation in relations.as_array()? { - if relation.get("type")?.as_str()? == "more-specific" { - for member in relation.get("members")?.as_array()? { - self.parse_member(member, &mut anns)?; - } - } - } - } - Some(anns) - } - - /// Parses the a single entry in the members array. - /// - /// Returns `None` if the JSON structure was in any way unexpected. - fn parse_member( - &self, member: &Value, anns: &mut Vec - ) -> Option<()> { - let prefix_str = member.get("prefix")?.as_str()?; - for meta in member.get("meta")?.as_array()? { - self.parse_meta(meta, prefix_str, anns)?; - } - Some(()) - } - - /// Parses the meta member of a result. - /// - /// Returns `None` if the JSON structure was in any way unexpected. - fn parse_meta( - &self, - meta: &Value, - prefix_str: &str, - anns: &mut Vec - ) -> Option<()> { - if meta.get("sourceType")?.as_str()? == "bgp" { - for asn in meta.get("originASNs")?.as_array()? { - // Strip off "AS" prefix - let asn = AsNumber::from_str(asn.as_str()?.get(2..)?).ok()?; - let prefix = TypedPrefix::from_str(prefix_str).ok()?; - - anns.push(Announcement { asn, prefix }); - } - } - Some(()) - } -} - - -//------------ ValidatedAnnouncement ----------------------------------------- - -/// A BGP announcement that has been validated agains ROAs. -#[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] -pub struct ValidatedAnnouncement { - /// The actual announcement. - pub announcement: Announcement, - - /// The RPKI validity status. - pub validity: AnnouncementValidity, - - /// The ROA payload that authorizes the announcement. - pub authorizing: Option, - - /// The ROA payload that disallows the announcement. - pub disallowing: Vec, -} - - -//------------ AnnouncementValidity ------------------------------------------ - -/// The RPKI validity of an announcement. -#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] -pub enum AnnouncementValidity { - /// The announcement is RPKI valid. - Valid, - - /// The announcement is RPKI valid because of the prefix length. - InvalidLength, - - /// The announcement is RPKI valid because of the originating ASN. - InvalidAsn, - - /// The announcement is not allowed. - Disallowed, - - /// The announcement is RPKI unknown. - NotFound, -} - - -//------------ IpRange ----------------------------------------------------- - -/// A range of IP addresses. -// -// We are using IPv4-mapped IPv6 addresses for IPv4 and can thus store -// everything as the `u128` of an IPv6 address. -#[derive(Clone, Debug)] -pub struct IpRange(Range); - -impl IpRange { - /// Returns the IPv4 (left) and IPv6 (right) ranges as a tuple. - pub fn from_resource_set( - set: &ResourceSet, - ) -> Vec { - let mut res = vec![]; - for block in set.ipv4().iter() { - res.push(IpRange(Range { - start: block.min().to_v4().to_ipv6_mapped().into(), - end: block.max().to_v4().to_ipv6_mapped().into(), - })) - } - for block in set.ipv6().iter() { - res.push(IpRange(Range { - start: block.min().to_v6().into(), - end: block.max().to_v6().into(), - })) - } - res - } - - /// Returns whether this range contains the other range. - fn contains(&self, other: &Range) -> bool { - self.0.start <= other.start && self.0.end >= other.end - } - - /// Returns whether this range is contained by the other range. - fn is_contained_by(&self, other: &Range) -> bool { - other.start <= self.0.start && other.end >= self.0.end - } - - /// Converts the range into a typed prefix. - pub fn to_prefixes(&self) -> Vec { - let is_ipv4 = - (self.0.start & 0xFFFF_FFFF_FFFF_FFFF_FFFF_FFFF_0000_0000) == - 0x0000_0000_0000_0000_0000_FFFF_0000_0000; - - let mut min = self.0.start; - let mut max = self.0.end; - - if is_ipv4 { - // Krill stores IPv4 internally as an IPv4-mapped IPv6 address, - // rpki-rs stores IPv4 addresses in the top bytes, so that prefix - // handling works regardless of the IP type. - min <<= 96; - max <<= 96; - } - - let range = AddressRange::from(( - Addr::from_bits(min), - Addr::from_bits(max) - )); - - match is_ipv4 { - true => range.to_v4_prefixes() - .map(|x| TypedPrefix::from(Ipv4Prefix::from(x))).collect(), - false => range.to_v6_prefixes() - .map(|x| TypedPrefix::from(Ipv6Prefix::from(x))).collect() - } - } -} - -impl From for IpRange { - fn from(tp: TypedPrefix) -> Self { - match tp { - TypedPrefix::V4(pfx) => { - let (min, max) = Prefix::from(pfx).range(); - let start = min.to_v4().to_ipv6_mapped().into(); - let end = max.to_v4().to_ipv6_mapped().into(); - IpRange(Range { start, end }) - } - TypedPrefix::V6(pfx) => { - let (min, max) = Prefix::from(pfx).range(); - let start = min.to_v6().into(); - let end = max.to_v6().into(); - IpRange(Range { start, end }) - } - } - } -} - - -//------------ IpRangeStore --------------------------------------------- - -pub struct IpRangeStore { - tree: IntervalTree>, -} - -impl IpRangeStore { - pub fn create(items: impl IntoIterator) -> Self { - let mut values: HashMap, Vec> = HashMap::new(); - for (range, value) in items { - values.entry(range.0).or_default().push(value); - } - IpRangeStore { tree: values.into_iter().collect() } - } - - pub fn matching_or_more_specific( - &self, - range: impl Into, - ) -> Vec<&V> { - let range: IpRange = range.into(); - let mut res = vec![]; - for el in self.tree.query(range.0.clone()) { - if range.contains(&el.range) { - for v in &el.value { - res.push(v) - } - } - } - res - } - - pub fn matching_or_less_specific( - &self, - range: impl Into, - ) -> Vec<&V> { - let range: IpRange = range.into(); - let mut res = vec![]; - for el in self.tree.query(range.0.clone()) { - if range.is_contained_by(&el.range) { - for v in &el.value { - res.push(v) - } - } - } - res - } - - pub fn size(&self) -> usize { - self.tree.iter().count() - } - - pub fn all(&self) -> Vec<&V> { - self.tree - .iter() - .flat_map(|el| el.value.as_slice()) - .collect() - } -} - -impl IpRangeStore { - fn validate_announcement( - &self, announcement: Announcement - ) -> ValidatedAnnouncement { - let covering = self.matching_or_less_specific(announcement.prefix); - if covering.is_empty() { - return ValidatedAnnouncement { - announcement, - validity: AnnouncementValidity::NotFound, - authorizing: None, - disallowing: vec![], - } - } - - let mut invalidating = vec![]; - let mut same_asn_found = false; - let mut none_as0_found = false; - for roa in covering { - if roa.asn == announcement.asn { - if roa.prefix.matching_or_less_specific(announcement.prefix) - && roa.effective_max_length() - >= announcement.prefix.addr_len() - { - return ValidatedAnnouncement { - announcement, - validity: AnnouncementValidity::Valid, - authorizing: Some(*roa), - disallowing: vec![], - }; - } - else { - same_asn_found = true; - } - } - if roa.asn != AsNumber::AS0 { - none_as0_found = true; - } - invalidating.push(*roa); - } - - // Valid announcements already returned, we only have invalids left. - let validity = if same_asn_found { - AnnouncementValidity::InvalidLength - } - else if none_as0_found { - AnnouncementValidity::InvalidAsn - } - else { - AnnouncementValidity::Disallowed - }; - - ValidatedAnnouncement { - announcement, - validity, - authorizing: None, - disallowing: invalidating, - } - } -} - - -//============ Error Types =================================================== - -//------------ BgpApiError --------------------------------------------------- - -/// An error happened whil accessing the BGP API. -#[derive(Debug)] -pub enum BgpApiError { - /// The HTTP request failed. - Reqwest(reqwest::Error), - - /// Decoding the content failed. - Serde(serde_json::Error), - - /// The data was malformed. - MalformedData -} - -impl From for BgpApiError { - fn from(e: reqwest::Error) -> BgpApiError { - BgpApiError::Reqwest(e) - } -} - -impl From for BgpApiError { - fn from(e: serde_json::Error) -> BgpApiError { - BgpApiError::Serde(e) - } -} - -impl fmt::Display for BgpApiError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - Self::Reqwest(err) => err.fmt(f), - Self::Serde(err) => err.fmt(f), - Self::MalformedData => f.write_str("malformed data") - } - } -} - -impl error::Error for BgpApiError { } - - -//============ Tests ========================================================= - -#[cfg(test)] -mod test { - use rpki::repository::resources::Prefix; - use crate::api::bgp::BgpAnalysisState; - use crate::api::roa::{ - Ipv4Prefix, Ipv6Prefix, RoaConfigurationUpdates - }; - use crate::commons::test::{configured_roa, roa_payload}; - use super::*; - - fn ann(s: &str) -> Announcement { - Announcement::from_str(s).unwrap() - } - - fn pfx(s: &str) -> TypedPrefix { - TypedPrefix::from_str(s).unwrap() - } - - fn range_pfx(s: &str) -> IpRange { - IpRange::from(pfx(s)) - } - - fn make_test_tree() -> IpRangeStore { - IpRangeStore::create( - [ - ann("10.0.0.0/24 => 64496"), - ann("10.0.1.0/24 => 64496"), - ann("10.0.0.0/23 => 64496"), - ann("10.0.0.0/20 => 64496"), - ann("10.0.0.0/16 => 64496"), - ].into_iter().map(|ann| (ann.prefix.into(), ann)) - ) - } - - #[tokio::test] - async fn analyse_bgp() { - let roa_too_permissive = configured_roa("10.0.0.0/22-23 => 64496"); - let roa_as0 = configured_roa("10.0.4.0/24 => 0"); - let roa_unseen_completely = configured_roa("10.0.3.0/24 => 64497"); - - let roa_not_held = configured_roa("10.1.0.0/24 => 64497"); - - let roa_authorizing_single = - configured_roa("192.168.1.0/24 => 64497"); - let roa_unseen_redundant = configured_roa("192.168.1.0/24 => 64498"); - let roa_as0_redundant = configured_roa("192.168.1.0/24 => 0"); - - let resources_held = - ResourceSet::from_strs("", "10.0.0.0/16, 192.168.0.0/16", "") - .unwrap(); - let limit = None; - - let analyser = BgpAnalyser::new( - true, "test".to_string(), Duration::default() - ); - - let report = analyser - .analyse( - &[ - roa_too_permissive, - roa_as0, - roa_unseen_completely, - roa_not_held, - roa_authorizing_single, - roa_unseen_redundant, - roa_as0_redundant, - ], - &resources_held, - limit, - ) - .await; - - let expected: BgpAnalysisReport = serde_json::from_str(include_str!( - "../../../test-resources/bgp/expected_full_report.json" - )) - .unwrap(); - - assert_eq!(report, expected); - } - - #[tokio::test] - async fn analyse_bgp_disallowed_announcements() { - let roa = configured_roa("10.0.0.0/22 => 0"); - - let roas = &[roa]; - let analyser = BgpAnalyser::new( - true, "test".to_string(), Duration::default(), - ); - - let resources_held = - ResourceSet::from_strs("", "10.0.0.0/8, 192.168.0.0/16", "") - .unwrap(); - let report = analyser.analyse(roas, &resources_held, None).await; - - assert!(!report.contains_invalids()); - - let mut disallowed = report - .matching_announcements(BgpAnalysisState::AnnouncementDisallowed); - disallowed.sort(); - - let disallowed_1 = ann("10.0.0.0/22 => 64496"); - let disallowed_2 = ann("10.0.0.0/22 => 64497"); - let disallowed_3 = ann("10.0.0.0/24 => 64496"); - let disallowed_4 = ann("10.0.2.0/23 => 64496"); - let mut expected = - vec![disallowed_1, disallowed_2, disallowed_3, disallowed_4]; - expected.sort(); - - assert_eq!(disallowed, expected); - - // The suggestion should not try to add the disallowed announcements - // because they were disallowed by an AS0 roa. - let suggestion = analyser.suggest(roas, &resources_held, None).await; - let updates = RoaConfigurationUpdates::from(suggestion); - - let added = &updates.added; - for announcement in disallowed { - assert!(!added.iter().any(|added_roa| { - let added_payload = added_roa.payload; - let announcement_payload = RoaPayload::from(announcement); - added_payload.includes(announcement_payload) - })); - } - } - - #[tokio::test] - async fn analyse_bgp_no_announcements() { - let roa1 = configured_roa("10.0.0.0/23-24 => 64496"); - let roa2 = configured_roa("10.0.3.0/24 => 64497"); - let roa3 = configured_roa("10.0.4.0/24 => 0"); - - let roas = vec![roa1, roa2, roa3]; - - let resources_held = - ResourceSet::from_strs("", "10.0.0.0/16", "").unwrap(); - - let analyser = BgpAnalyser::new( - false, "".to_string(), Duration::default() - ); - let table = analyser.analyse(&roas, &resources_held, None).await; - let table_entries = table.entries(); - assert_eq!(3, table_entries.len()); - - let roas_no_info: Vec = table_entries - .iter() - .filter(|e| e.state() == BgpAnalysisState::RoaNoAnnouncementInfo) - .map(|e| e.configured_roa().clone()) - .collect(); - - assert_eq!(roas_no_info, roas); - } - - #[tokio::test] - async fn make_bgp_analysis_suggestion() { - let roa_too_permissive = configured_roa("10.0.0.0/22-23 => 64496"); - let roa_redundant = configured_roa("10.0.0.0/23 => 64496"); - let roa_as0 = configured_roa("10.0.4.0/24 => 0"); - let roa_unseen_completely = configured_roa("10.0.3.0/24 => 64497"); - let roa_authorizing_single = - configured_roa("192.168.1.0/24 => 64497"); - let roa_unseen_redundant = configured_roa("192.168.1.0/24 => 64498"); - let roa_as0_redundant = configured_roa("192.168.1.0/24 => 0"); - - let roas = &[ - roa_too_permissive, - roa_redundant, - roa_as0, - roa_unseen_completely, - roa_authorizing_single, - roa_unseen_redundant, - roa_as0_redundant, - ]; - - let analyser = BgpAnalyser::new( - true, "test".to_string(), Duration::default() - ); - - let resources_held = - ResourceSet::from_strs("", "10.0.0.0/8, 192.168.0.0/16", "") - .unwrap(); - let limit = - Some(ResourceSet::from_strs("", "10.0.0.0/22", "").unwrap()); - let suggestion_resource_subset = - analyser.suggest(roas, &resources_held, limit).await; - - let expected: BgpAnalysisSuggestion = - serde_json::from_str(include_str!( - "../../../test-resources/bgp/expected_suggestion_some_roas.json" - )) - .unwrap(); - assert_eq!(suggestion_resource_subset, expected); - - let suggestion_all_roas_in_scope = - analyser.suggest(roas, &resources_held, None).await; - - let expected: BgpAnalysisSuggestion = - serde_json::from_str(include_str!( - "../../../test-resources/bgp/expected_suggestion_all_roas.json" - )) - .unwrap(); - - assert_eq!(suggestion_all_roas_in_scope, expected); - } - - #[test] - fn format_url() { - let analyser = BgpAnalyser::new( - true, "https://rest.bgp-api.net".to_string(), Duration::default() - ); - assert_eq!( - "https://rest.bgp-api.net/api/v1/prefix/192.168.0.0/16/search", - analyser.format_url(TypedPrefix::from(Ipv4Prefix::from( - Prefix::from_str("192.168.0.0/16").unwrap() - ))) - ); - assert_eq!( - "https://rest.bgp-api.net/api/v1/prefix/2001:db8::/32/search", - analyser.format_url(TypedPrefix::from(Ipv6Prefix::from( - Prefix::from_str("2001:db8::/32").unwrap() - ))) - ); - } - - #[tokio::test] - async fn retrieve_announcements() { - let analyser = BgpAnalyser::new( - true, "test".to_string(), Duration::default() - ); - - let ipv4s = "185.49.140.0/22"; - let ipv6s = "2a04:b900::/29"; - - let ranges = IpRange::from_resource_set( - &ResourceSet::from_strs("", ipv4s, "").unwrap() - ); - for range in ranges { - assert_eq!(3, analyser.retrieve(range).await.unwrap().len()); - } - - let ranges = IpRange::from_resource_set( - &ResourceSet::from_strs("", "", ipv6s).unwrap() - ); - for range in ranges { - assert_eq!(6, analyser.retrieve(range).await.unwrap().len()); - } - } - - #[tokio::test] - async fn retrieve_broken_announcements() { - let analyser = BgpAnalyser::new( - true, "test".to_string(), Duration::default() - ); - - let ipv4s = "1.1.1.1/32, 3.3.3.3/32, 4.4.4.4/32"; - let set = ResourceSet::from_strs("", ipv4s, "").unwrap(); - - let ranges = IpRange::from_resource_set(&set); - - for range in ranges { - assert!(analyser.retrieve(range).await.is_err()); - } - } - - #[tokio::test] - async fn analyse_nlnet_labs_snapshot() { - let analyser = BgpAnalyser::new( - true, "test".to_string(), Duration::default() - ); - - let ipv4s = "185.49.140.0/22"; - let ipv6s = "2a04:b900::/29"; - let set = ResourceSet::from_strs("AS211321", ipv4s, ipv6s).unwrap(); - - let roas = &[ - configured_roa("2a04:b906::/48-48 => 0"), - configured_roa("2a04:b907::/48-48 => 0"), - configured_roa("185.49.142.0/24-24 => 0"), - configured_roa("2a04:b900::/30-32 => 8587"), - configured_roa("185.49.140.0/23-23 => 8587"), - configured_roa("2a04:b900::/30-30 => 8587"), - configured_roa("2a04:b905::/48-48 => 14618"), - configured_roa("2a04:b905::/48-48 => 16509"), - configured_roa("2a04:b902::/32-32 => 16509"), - configured_roa("2a04:b904::/48-48 => 211321"), - configured_roa("2a04:b907::/47-47 => 211321"), - configured_roa("185.49.142.0/23-23 => 211321"), - configured_roa("2a04:b902::/48-48 => 211321"), - configured_roa("185.49.143.0/24-24 => 211321"), - ]; - - let report = analyser.analyse(roas, &set, None).await; - - let entry_expect_roa = |x: &str, y| { - let x = x.to_string(); - assert!(report.entries().iter().any(|s| - s.state() == y && - s.configured_roa().to_string() == x - )); - }; - - let entry_expect_ann = |x: &str, y: u32, z: BgpAnalysisState| { - let x = x.to_string(); - assert!(report.entries().iter().any(|s| - s.state() == z && - s.announcement().asn == AsNumber::from_u32(y) && - s.announcement().prefix.to_string() == x - )); - }; - - entry_expect_roa( - "2a04:b907::/48-48 => 0", BgpAnalysisState::RoaAs0Redundant - ); - entry_expect_roa( - "185.49.142.0/24-24 => 0", BgpAnalysisState::RoaAs0Redundant - ); - entry_expect_roa( - "2a04:b900::/30-30 => 8587", BgpAnalysisState::RoaRedundant - ); - entry_expect_roa( - "2a04:b905::/48-48 => 14618", BgpAnalysisState::RoaUnseen - ); - entry_expect_roa( - "2a04:b902::/32-32 => 16509", BgpAnalysisState::RoaUnseen - ); - entry_expect_ann( - "2a04:b907::/48", 211321, - BgpAnalysisState::AnnouncementInvalidLength - ); - entry_expect_ann( - "185.49.142.0/24", 211321, - BgpAnalysisState::AnnouncementInvalidLength - ); - entry_expect_roa( - "2a04:b902::/48-48 => 211321", BgpAnalysisState::RoaUnseen - ); - entry_expect_roa( - "185.49.143.0/24-24 => 211321", BgpAnalysisState::RoaUnseen - ); - } - - #[test] - fn validate_announcement() { - let roas = [ - roa_payload("10.0.0.0/23-24 => 64496"), // authorizing 1 - roa_payload("10.0.0.0/23 => 64498"), // authorizing 2 - roa_payload("10.1.0.0/23-24 => 64496") // irrelevant, - ]; - - let ann_v1 = ann("10.0.0.0/24 => 64496"); - let ann_v2 = ann("10.0.1.0/24 => 64496"); - let ann_ia = ann("10.0.0.0/24 => 64497"); - let ann_il = ann("10.0.1.0/24 => 64498"); - let ann_nf = ann("10.2.0.0/24 => 64497"); - - let roas = IpRangeStore::create( - roas.into_iter().map(|roa| (roa.prefix.into(), roa)) - ); - - fn assert_state( - ann: &Announcement, - roas: &IpRangeStore, - expected: AnnouncementValidity, - ) { - assert_eq!(roas.validate_announcement(*ann).validity, expected); - } - - assert_state(&ann_v1, &roas, AnnouncementValidity::Valid); - assert_state(&ann_v2, &roas, AnnouncementValidity::Valid); - assert_state(&ann_ia, &roas, AnnouncementValidity::InvalidAsn); - assert_state(&ann_il, &roas, AnnouncementValidity::InvalidLength); - assert_state(&ann_nf, &roas, AnnouncementValidity::NotFound); - } - - #[test] - fn range_contains() { - let more_specific_1 = range_pfx("10.0.0.0/24"); - let more_specific_2 = range_pfx("10.0.1.0/24"); - let test_pfx = range_pfx("10.0.0.0/23"); - - assert!(test_pfx.contains(&more_specific_1.0)); - assert!(test_pfx.contains(&more_specific_2.0)); - } - - #[test] - fn typed_prefix_tree_more_specific() { - let tree = make_test_tree(); - let search = TypedPrefix::from_str("10.0.0.0/23").unwrap(); - assert_eq!(3, tree.matching_or_more_specific(search).len()); - - let search = TypedPrefix::from_str("10.0.2.0/24").unwrap(); - assert_eq!(0, tree.matching_or_more_specific(search).len()); - } - - #[test] - fn typed_prefix_tree_less_specific() { - let tree = make_test_tree(); - let search = TypedPrefix::from_str("10.0.0.0/23").unwrap(); - assert_eq!(3, tree.matching_or_less_specific(search).len()); - - let search = TypedPrefix::from_str("10.0.0.0/24").unwrap(); - assert_eq!(4, tree.matching_or_less_specific(search).len()); - - let search = TypedPrefix::from_str("10.0.0.0/16").unwrap(); - assert_eq!(1, tree.matching_or_less_specific(search).len()); - - let search = TypedPrefix::from_str("10.0.0.0/15").unwrap(); - assert_eq!(0, tree.matching_or_less_specific(search).len()); - } - - #[test] - fn set_to_ranges() { - let asns = "AS65000-AS65003, AS65005"; - let ipv4s = "10.0.0.0/8, 192.168.0.0"; - let ipv6s = "::1, 2001:db8::/32"; - let set = ResourceSet::from_strs(asns, ipv4s, ipv6s).unwrap(); - - let ranges = IpRange::from_resource_set(&set); - assert_eq!(4, ranges.len()); - } - - #[test] - fn to_prefixes() { - let ipv4s = "10.0.0.0/8, 192.168.0.0-192.168.2.255"; - let ipv6s = "::1-::3, 2001:db8::/32"; - let set = ResourceSet::from_strs("", ipv4s, ipv6s).unwrap(); - - let ranges: Vec> = - IpRange::from_resource_set(&set) - .into_iter() - .map(|x| x.to_prefixes()) - .collect(); - - assert_eq!(1, ranges[0].len()); - assert_eq!(2, ranges[1].len()); - assert_eq!(2, ranges[2].len()); - assert_eq!(1, ranges[3].len()); - } - - #[tokio::test] - async fn correct_analysis() { - let analyser = BgpAnalyser::new( - true, "test".to_string(), Duration::default() - ); - - let ipv4s = "103.60.200.0/22, 103.160.116.0/23, 103.184.174.0/23, 103.233.208.0/22, 122.99.120.0/22, 202.14.148.0/24, 203.0.80.0/24, 203.1.68.0/23"; - let ipv6s = ""; - let set = ResourceSet::from_strs("AS1000-1200", ipv4s, ipv6s).unwrap(); - - let roas = &[ - configured_roa("103.60.200.0/22-22 => 211321"), - configured_roa("103.160.116.0/23-23 => 211321"), - configured_roa("103.184.174.0/23-23 => 211321"), - configured_roa("103.233.208.0/22-22 => 211321"), - configured_roa("122.99.120.0/22-22 => 211321"), - configured_roa("202.14.148.0/24-24 => 211321"), - configured_roa("203.0.80.0/24-24 => 211321"), - configured_roa("203.1.68.0/23-23 => 211321"), - ]; - - for block in IpRange::from_resource_set(&set) { - assert!(analyser.retrieve(block).await.is_ok()); - } - - let report = analyser.analyse(roas, &set, None).await; - - let mut expected_results = vec![ - BgpAnalysisState::RoaUnseen, - BgpAnalysisState::RoaDisallowing, - BgpAnalysisState::RoaDisallowing, - BgpAnalysisState::RoaDisallowing, - BgpAnalysisState::RoaDisallowing, - BgpAnalysisState::RoaDisallowing, - BgpAnalysisState::RoaDisallowing, - BgpAnalysisState::RoaDisallowing, - BgpAnalysisState::AnnouncementInvalidAsn, - BgpAnalysisState::AnnouncementInvalidAsn, - BgpAnalysisState::AnnouncementInvalidAsn, - BgpAnalysisState::AnnouncementInvalidAsn, - BgpAnalysisState::AnnouncementInvalidAsn, - BgpAnalysisState::AnnouncementInvalidAsn, - BgpAnalysisState::AnnouncementInvalidAsn, - BgpAnalysisState::AnnouncementInvalidAsn, - BgpAnalysisState::AnnouncementInvalidAsn, - BgpAnalysisState::AnnouncementInvalidAsn, - BgpAnalysisState::AnnouncementInvalidAsn, - BgpAnalysisState::AnnouncementInvalidAsn, - BgpAnalysisState::AnnouncementInvalidAsn, - BgpAnalysisState::AnnouncementInvalidAsn, - BgpAnalysisState::AnnouncementInvalidAsn, - BgpAnalysisState::AnnouncementInvalidAsn, - ]; - expected_results.reverse(); - for entry in report.entries() { - assert_eq!(expected_results.pop().unwrap(), entry.state()); - } - } -} diff --git a/src/server/ca/aspa.rs b/src/server/ca/aspa.rs index b342b3c5..4cbf55f6 100644 --- a/src/server/ca/aspa.rs +++ b/src/server/ca/aspa.rs @@ -333,7 +333,7 @@ impl AspaObjects { ); object_builder.set_issuer( Some(certified_key.incoming_cert().subject.clone())); - object_builder.set_signing_time(Some(Time::now())); + object_builder.set_signing_time(Time::now()); object_builder }; diff --git a/src/server/ca/certauth.rs b/src/server/ca/certauth.rs index b929283c..db30411c 100644 --- a/src/server/ca/certauth.rs +++ b/src/server/ca/certauth.rs @@ -230,7 +230,9 @@ impl Aggregate for CertAuth { } CertAuthCommandDetails::ChildUnsuspend(child) => { - self.process_child_unsuspend(&child) + self.process_child_unsuspend( + &child, krill.config(), krill.signer() + ) } @@ -1586,6 +1588,8 @@ impl CertAuth { fn process_child_unsuspend( &self, child_handle: &ChildHandle, + config: &Config, + signer: &KrillSigner, ) -> KrillResult> { let child = self.get_child(child_handle)?; @@ -1613,11 +1617,18 @@ impl CertAuth { > Time::now() + Duration::days(1) && child.resources.contains(&suspended.resources) { - // certificate is still fit for publication, so move - // it back to issued - cert_updates.unsuspended.push( - suspended.to_converted() - ); + // reissue a new certificate because the old one is on + // the CRL. + self.append_child_certify( + child_handle.clone(), + &suspended.resources, + rcn.clone(), + suspended.csr_info.clone(), + suspended.limit.clone(), + config, + signer, + &mut res, + )?; } else { // certificate should not be published as is. Remove @@ -2628,7 +2639,7 @@ impl CertAuth { // submitted keys) and add the cert for (_rcn, ee) in rc_ee.into_iter() { let ee_key = ee.subject_key_identifier(); - signer.sign_rta(&mut rta_builder, ee)?; + signer.sign_rta(&mut rta_builder, Time::now(), ee)?; signer.destroy_key(&ee_key)?; } diff --git a/src/server/ca/child.rs b/src/server/ca/child.rs index 03190464..46f098bf 100644 --- a/src/server/ca/child.rs +++ b/src/server/ca/child.rs @@ -181,7 +181,7 @@ pub struct ChildCertificates { #[serde(alias = "inner")] issued: HashMap, - /// The certificates for suspeneded child CAs. + /// The certificates for suspended child CAs. #[serde( skip_serializing_if = "HashMap::is_empty", default = "HashMap::new" @@ -396,6 +396,9 @@ pub struct ChildCertificateUpdates { pub suspended: Vec, /// The certificats that have been unsuspended. + /// + /// This is no longer used as of Krill 0.16.0, but kept because it is in + /// stored state. #[serde(skip_serializing_if = "Vec::is_empty", default)] pub unsuspended: Vec, } diff --git a/src/server/ca/keys.rs b/src/server/ca/keys.rs index 317aecca..a7405621 100644 --- a/src/server/ca/keys.rs +++ b/src/server/ca/keys.rs @@ -78,6 +78,7 @@ impl CertifiedKey { /// Updates the certificate received for the key. pub fn set_incoming_cert(&mut self, cert: ReceivedCert) { + self.request = None; self.incoming_cert = cert } diff --git a/src/server/ca/publishing.rs b/src/server/ca/publishing.rs index 9098006a..d7425512 100644 --- a/src/server/ca/publishing.rs +++ b/src/server/ca/publishing.rs @@ -1321,16 +1321,13 @@ impl KeyObjectSet { } } + // Since Krill 0.16 suspended certificates will reissued rather than + // unsuspended, so this does nothing anymore except for migrations. for cert in &cert_updates.unsuspended { - self.revocations.remove(&cert.revocation()); let published_object = PublishedObject::for_cert_info(cert); - if let Some(old) = self - .published_objects - .insert(cert.name.clone(), published_object) - { - // this should not happen, but just to be safe. - self.revocations.add(old.revoke()); - } + self.published_objects.insert( + cert.name.clone(), published_object + ); } for suspended in &cert_updates.suspended { @@ -1743,7 +1740,7 @@ impl ManifestBuilder { mft_uri, ); object_builder.set_issuer(Some(signing_cert.subject.clone())); - object_builder.set_signing_time(Some(Time::now())); + object_builder.set_signing_time(Time::now()); signer.sign_manifest(mft_content, object_builder, &aki)? }; diff --git a/src/server/ca/roa.rs b/src/server/ca/roa.rs index 0ebaa840..95a84489 100644 --- a/src/server/ca/roa.rs +++ b/src/server/ca/roa.rs @@ -868,7 +868,7 @@ impl Roas { object_builder.set_issuer( Some(certified_key.incoming_cert().subject.clone()) ); - object_builder.set_signing_time(Some(Time::now())); + object_builder.set_signing_time(Time::now()); Ok(signer.sign_roa( roa_builder, object_builder, &certified_key.key_id() diff --git a/src/server/mq.rs b/src/server/mq.rs index 0351262e..8608bb8b 100644 --- a/src/server/mq.rs +++ b/src/server/mq.rs @@ -293,7 +293,6 @@ impl TaskQueue { } impl TaskQueue { pub fn pop(&self) -> Option<(Box, serde_json::Value)> { - trace!("Try to get a task off the queue"); match self.q.claim_scheduled_pending_task() { Err(e) => { // Log error and return nothing. @@ -305,11 +304,9 @@ impl TaskQueue { None } Ok(None) => { - trace!("No pending task found."); None } Ok(Some((key, value))) => { - trace!("found task: {key}"); Some((key, value)) } } diff --git a/src/server/scheduler.rs b/src/server/scheduler.rs index 7c982390..348f25b3 100644 --- a/src/server/scheduler.rs +++ b/src/server/scheduler.rs @@ -13,7 +13,7 @@ use crate::{ api::ca::Timestamp, commons::{ crypto::dispatch::signerinfo::SignerInfo, - error::FatalError, + error::{Error, FatalError}, eventsourcing::{Aggregate, AggregateStore, WalStore, WalSupport}, storage::Ident, version::KrillVersion, @@ -355,11 +355,22 @@ fn sync_parent( Err(e) => { let next = krill.config().requeue_remote_failed(); - error!( - "Failed to synchronize CA '{ca}' with its parent \ - '{parent}'. Will reschedule to: '{next}'. Error: {e}" - ); - Ok(TaskResult::Reschedule(next)) + if let Error::CaParentUnknown(..) = e { + warn!( + "CA '{ca}' tried to sync with parent '{parent}'. + Parent is unknown. Not rescheduling. Error: {e} + " + ); + + Ok(TaskResult::Done) + } + else { + error!( + "Failed to synchronize CA '{ca}' with its parent \ + '{parent}'. Will reschedule to: '{next}'. Error: {e}" + ); + Ok(TaskResult::Reschedule(next)) + } } Ok(true) => { let next = krill.config().ca_refresh_next();