From dff40a42d9112c612bba43dce8597f81924cf298 Mon Sep 17 00:00:00 2001 From: Flavio Castelli Date: Tue, 1 Oct 2024 08:59:28 +0200 Subject: [PATCH 1/5] Initial implementation Implement policy Signed-off-by: Flavio Castelli --- Cargo.lock | 971 ++++++++++++++++++ Cargo.toml | 5 +- README.md | 64 +- artifacthub-pkg.yml | 56 +- e2e.bats | 36 +- metadata.yml | 24 +- questions-ui.yml | 1 + src/lib.rs | 219 ++-- src/settings.rs | 33 +- test_data/ingress_creation.json | 59 -- ...nvalid_name.json => pod_with_5_ndots.json} | 8 + ...d_creation.json => pod_without_ndots.json} | 0 test_data/settings-5-ndots.yaml | 1 + 13 files changed, 1226 insertions(+), 251 deletions(-) create mode 100644 Cargo.lock create mode 100644 questions-ui.yml delete mode 100644 test_data/ingress_creation.json rename test_data/{pod_creation_invalid_name.json => pod_with_5_ndots.json} (84%) rename test_data/{pod_creation.json => pod_without_ndots.json} (100%) create mode 100644 test_data/settings-5-ndots.yaml diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..86af144 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,971 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.89" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "chrono" +version = "0.4.38" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" +dependencies = [ + "num-traits", + "serde", +] + +[[package]] +name = "darling" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn", +] + +[[package]] +name = "darling_macro" +version = "0.20.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +dependencies = [ + "darling_core", + "quote", + "syn", +] + +[[package]] +name = "derive_builder" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd33f37ee6a119146a1781d3356a7c26028f83d779b2e04ecd45fdc75c76877b" +dependencies = [ + "derive_builder_macro", +] + +[[package]] +name = "derive_builder_core" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7431fa049613920234f22c47fdc33e6cf3ee83067091ea4277a3f8c4587aae38" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "derive_builder_macro" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4abae7035bf79b9877b779505d8cf3749285b80c43941eda66604841889451dc" +dependencies = [ + "derive_builder_core", + "syn", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[package]] +name = "futures-executor" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" + +[[package]] +name = "futures-macro" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "futures-sink" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" + +[[package]] +name = "futures-task" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" + +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + +[[package]] +name = "futures-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getset" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f636605b743120a8d32ed92fc27b6cde1a769f8f936c065151eb66f88ded513c" +dependencies = [ + "proc-macro-error2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "k8s-openapi" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8847402328d8301354c94d605481f25a6bdc1ed65471fd96af8eca71141b13" +dependencies = [ + "base64", + "chrono", + "serde", + "serde-value", + "serde_json", +] + +[[package]] +name = "kubewarden-policy-sdk" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c5d198c30461d4ee3b0bb8733904aacd17ebe021c386cee369f4d9fc9f3df24" +dependencies = [ + "anyhow", + "cfg-if", + "chrono", + "k8s-openapi", + "num", + "num-derive", + "num-traits", + "oci-spec", + "serde", + "serde_json", + "serde_yaml", + "slog", + "url", + "wapc-guest", +] + +[[package]] +name = "libc" +version = "0.2.159" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "num" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35bd024e8b2ff75562e5f34e7f4905839deb4b22955ef5e73d2fea1b9813cb23" +dependencies = [ + "num-bigint", + "num-complex", + "num-integer", + "num-iter", + "num-rational", + "num-traits", +] + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + +[[package]] +name = "oci-spec" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5cee185ce7cf1cce45e194e34cd87c0bad7ff0aa2e8917009a2da4f7b31fb363" +dependencies = [ + "derive_builder", + "getset", + "regex", + "serde", + "serde_json", + "strum", + "strum_macros", + "thiserror", +] + +[[package]] +name = "once_cell" +version = "1.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" +dependencies = [ + "portable-atomic", +] + +[[package]] +name = "ordered-float" +version = "2.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c" +dependencies = [ + "num-traits", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "pod-ndots" +version = "0.1.0" +dependencies = [ + "k8s-openapi", + "kubewarden-policy-sdk", + "rstest", + "serde", + "serde_json", +] + +[[package]] +name = "portable-atomic" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc9c68a3f6da06753e9335d63e27f6b9754dd1920d941135b7ea8224f141adb2" + +[[package]] +name = "proc-macro-crate" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" +dependencies = [ + "toml_edit", +] + +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "proc-macro2" +version = "1.0.86" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "relative-path" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2" + +[[package]] +name = "rstest" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a2c585be59b6b5dd66a9d2084aa1d8bd52fbdb806eafdeffb52791147862035" +dependencies = [ + "futures", + "futures-timer", + "rstest_macros", + "rustc_version", +] + +[[package]] +name = "rstest_macros" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "825ea780781b15345a146be27eaefb05085e337e869bff01b4306a4fd4a9ad5a" +dependencies = [ + "cfg-if", + "glob", + "proc-macro-crate", + "proc-macro2", + "quote", + "regex", + "relative-path", + "rustc_version", + "syn", + "unicode-ident", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + +[[package]] +name = "rustversion" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955d28af4278de8121b7ebeb796b6a45735dc01436d898801014aced2773a3d6" + +[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "semver" +version = "1.0.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-value" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c" +dependencies = [ + "ordered-float", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.128" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_yaml" +version = "0.9.34+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +dependencies = [ + "indexmap", + "itoa", + "ryu", + "serde", + "unsafe-libyaml", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "slog" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8347046d4ebd943127157b94d63abb990fcf729dc4e9978927fdf4ac3c998d06" + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + +[[package]] +name = "strum" +version = "0.26.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" + +[[package]] +name = "strum_macros" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6bee85a5a24955dc440386795aa378cd9cf82acd5f764469152d2270e581be" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "rustversion", + "syn", +] + +[[package]] +name = "syn" +version = "2.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "toml_datetime", + "winnow", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unsafe-libyaml" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "wapc-guest" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57b7619cdb37b84600569a46fe2e9ded4b5a68acc394efbe40092fb63ff2808c" +dependencies = [ + "once_cell", + "parking_lot", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] diff --git a/Cargo.toml b/Cargo.toml index 3fe2751..7b0e5d3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,8 @@ k8s-openapi = { version = "0.23.0", default-features = false, features = [ "v1_30", ] } kubewarden-policy-sdk = "0.11.1" -lazy_static = "1.5" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" -slog = "2.7" + +[dev-dependencies] +rstest = "0.23" diff --git a/README.md b/README.md index 230e6ca..5357ece 100644 --- a/README.md +++ b/README.md @@ -1,40 +1,50 @@ +[![Kubewarden Policy Repository](https://github.com/kubewarden/community/blob/main/badges/kubewarden-policies.svg)](https://github.com/kubewarden/community/blob/main/REPOSITORIES.md#policy-scope) [![Stable](https://img.shields.io/badge/status-stable-brightgreen?style=for-the-badge)](https://github.com/kubewarden/community/blob/main/REPOSITORIES.md#stable) -Please, note well: this file and the scaffold were generated from [a -template](https://github.com/kubewarden/rust-policy-template). Make -this project yours! +Kubewarden policy that enforces the DNS lookup configuration of a Pod to have a specific `ndots` value. -You can use `cargo generate -g https://github.com/kubewarden/rust-policy-template.git` -to create your Policy from this template. +This is done by mutating the Pod's `.spec.dnsConfig.options` field to have the desired `ndots` value. -# Kubewarden policy pod-ndots +# Configuration -## Description +The number of `ndots` to enforce can be configured using the `ndots` field. -This policy will reject pods that have a name `invalid-pod-name`. If -the pod to be validated has a different name, or if a different type -of resource is evaluated, it will be accepted. - -## Settings +```yaml +ndots: 2 +``` -This policy has no configurable settings. This would be a good place -to document if yours does, and what behaviors can be configured by -tweaking them. +When no configuration is provided, the default value is `1`. -## License +## Examples -``` -Copyright (C) 2021 Flavio Castelli +Assuming the no configuration is provided, the policy will enforce the `ndots` value to be `1`. -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at +This will change the following Pod: - http://www.apache.org/licenses/LICENSE-2.0 +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: nginx +spec: + containers: + - name: nginx + image: nginx +``` -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. +To the following Pod: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: nginx +spec: + dnsConfig: + options: + - name: ndots + value: "1" + containers: + - name: nginx + image: nginx ``` diff --git a/artifacthub-pkg.yml b/artifacthub-pkg.yml index 5a8e618..127c7ca 100644 --- a/artifacthub-pkg.yml +++ b/artifacthub-pkg.yml @@ -1,30 +1,54 @@ ---- -### -### Use `make artifacthub-pkg.yml` to auto-generate this file -### See docs.kubewarden.io for publishing to ArtifactHub -### +# Kubewarden Artifacthub Package config +# +# Use this config to submit the policy to https://artifacthub.io. +# +# This config can be saved to its default location with: +# kwctl scaffold artifacthub > artifacthub-pkg.yml version: 0.1.0 name: pod-ndots -displayName: LIKE NAME, BUT FANCIER -createdAt: '2022-07-19T16:39:10+02:00' -description: DESCRIPTION OF YOUR POLICY +displayName: Pod ndots +createdAt: 2024-10-01T06:58:50.339806282Z +description: Enforce a minimum value for the ndots option in the resolv.conf file of a Pod. license: Apache-2.0 -homeURL: https://author1.website +homeURL: https://github.com/kubewarden/pod-ndots containersImages: - name: policy - image: "ghcr.io/kubewarden/policies/pod-ndots:v0.1.0" + image: ghcr.io/kubewarden/policies/pod-ndots:v0.1.0 keywords: -- this is freeform +- pod links: - name: policy - url: https://github.com/yourorg/pod-ndots/releases/download/v0.1.0/policy.wasm + url: https://github.com/kubewarden/pod-ndots/releases/download/v0.1.0/policy.wasm - name: source - url: POLICY HOMEPAGE URL + url: https://github.com/kubewarden/pod-ndots +install: | + The policy can be obtained using [`kwctl`](https://github.com/kubewarden/kwctl): + ```console + kwctl pull ghcr.io/kubewarden/policies/pod-ndots:v0.1.0 + ``` + Then, generate the policy manifest and tune it to your liking. For example: + ```console + kwctl scaffold manifest -t ClusterAdmissionPolicy registry://ghcr.io/kubewarden/policies/pod-ndots:v0.1.0 + ``` +maintainers: +- name: Kubewarden Developers + email: kubewarden@suse.de provider: name: kubewarden recommendations: - url: https://artifacthub.io/packages/helm/kubewarden/kubewarden-controller annotations: - kubewarden/resources: Pod # comma separated list - kubewarden/mutation: false - kubewarden/contextAware: false + kubewarden/mutation: 'true' + kubewarden/questions-ui: | + questions: + kubewarden/resources: Pod + kubewarden/rules: | + - apiGroups: + - '' + apiVersions: + - v1 + resources: + - pods + operations: + - CREATE + - UPDATE diff --git a/e2e.bats b/e2e.bats index a5c55f9..36916a0 100644 --- a/e2e.bats +++ b/e2e.bats @@ -1,32 +1,30 @@ #!/usr/bin/env bats -@test "Accept a valid name" { - run kwctl run --request-path test_data/pod_creation.json annotated-policy.wasm +@test "Mutate pod definition" { + # Need to run the command inside of `bash -c` because of a bats + # limitation: https://bats-core.readthedocs.io/en/stable/gotchas.html?highlight=pipe#my-piped-command-does-not-work-under-run + run bash -c 'kwctl run \ + --request-path test_data/pod_with_5_ndots.json \ + annotated-policy.wasm 2>/dev/null | jq -er ".patch | @base64d"' # this prints the output when one the checks below fails echo "output = ${output}" - [ "$status" -eq 0 ] - [ $(expr "$output" : '.*"allowed":true.*') -ne 0 ] + [ "$status" -eq 0 ] + [ $(expr "$output" : '.*{"op":"replace","path":"/spec/dnsConfig/options/0/value","value":"1"}.*') -ne 0 ] } -@test "Accept requests involving a non-Pod resource" { - run kwctl run --request-path test_data/ingress_creation.json annotated-policy.wasm +@test "Do not mutate Pod definition" { + # Need to run the command inside of `bash -c` because of a bats + # limitation: https://bats-core.readthedocs.io/en/stable/gotchas.html?highlight=pipe#my-piped-command-does-not-work-under-run + run bash -c 'kwctl run \ + --request-path test_data/pod_with_5_ndots.json \ + --settings-path test_data/settings-5-ndots.yaml \ + annotated-policy.wasm 2>/dev/null | jq -er ".patch"' # this prints the output when one the checks below fails echo "output = ${output}" - [ "$status" -eq 0 ] - [ $(expr "$output" : '.*"allowed":true.*') -ne 0 ] -} - -@test "Reject invalid name" { - run kwctl run --request-path test_data/pod_creation_invalid_name.json annotated-policy.wasm - - # this prints the output when one the checks below fails - echo "output = ${output}" - - [ "$status" -eq 0 ] - [ $(expr "$output" : '.*"allowed":false.*') -ne 0 ] - [ $(expr "$output" : '.*"message":"pod name invalid-pod-name is not accepted".*') -ne 0 ] + [ "$status" -eq 1 ] + [ $(expr "$output" : 'null') -ne 0 ] } diff --git a/metadata.yml b/metadata.yml index 527a648..834b6b4 100644 --- a/metadata.yml +++ b/metadata.yml @@ -1,9 +1,9 @@ rules: -- apiGroups: [""] - apiVersions: ["v1"] - resources: ["pods"] - operations: ["CREATE"] -mutating: false + - apiGroups: [""] + apiVersions: ["v1"] + resources: ["pods"] + operations: ["CREATE", "UPDATE"] +mutating: true contextAwareResources: [] executionMode: kubewarden-wapc # Consider the policy for the background audit scans. Default is true. Note the @@ -13,19 +13,19 @@ executionMode: kubewarden-wapc backgroundAudit: true annotations: # artifacthub specific: - io.artifacthub.displayName: Policy Name + io.artifacthub.displayName: Pod ndots io.artifacthub.resources: Pod - io.artifacthub.keywords: pod, cool policy, kubewarden + io.artifacthub.keywords: pod io.kubewarden.policy.ociUrl: ghcr.io/kubewarden/policies/pod-ndots # kubewarden specific: io.kubewarden.policy.title: pod-ndots - io.kubewarden.policy.description: Short description - io.kubewarden.policy.author: Flavio Castelli - io.kubewarden.policy.url: https://github.com/yourorg/pod-ndots - io.kubewarden.policy.source: https://github.com/yourorg/pod-ndots + io.kubewarden.policy.description: Enforce a minimum value for the ndots option in the resolv.conf file of a Pod. + io.kubewarden.policy.author: Kubewarden Developers + io.kubewarden.policy.url: https://github.com/kubewarden/pod-ndots + io.kubewarden.policy.source: https://github.com/kubewarden/pod-ndots io.kubewarden.policy.license: Apache-2.0 # The next two annotations are used in the policy report generated by the # Audit scanner. Severity indicates policy check result criticality and # Category indicates policy category. See more here at docs.kubewarden.io - io.kubewarden.policy.severity: medium + io.kubewarden.policy.severity: low io.kubewarden.policy.category: Resource validation diff --git a/questions-ui.yml b/questions-ui.yml new file mode 100644 index 0000000..77bfa09 --- /dev/null +++ b/questions-ui.yml @@ -0,0 +1 @@ +questions: diff --git a/src/lib.rs b/src/lib.rs index c36d343..a8ff54b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,26 +1,15 @@ -use lazy_static::lazy_static; - use guest::prelude::*; use kubewarden_policy_sdk::wapc_guest as guest; -use k8s_openapi::api::core::v1 as apicore; +use k8s_openapi::api::core::v1::{self as apicore, PodSpec}; use k8s_openapi::Resource; extern crate kubewarden_policy_sdk as kubewarden; -use kubewarden::{logging, protocol_version_guest, request::ValidationRequest, validate_settings}; +use kubewarden::{protocol_version_guest, request::ValidationRequest, validate_settings}; mod settings; use settings::Settings; -use slog::{info, o, warn, Logger}; - -lazy_static! { - static ref LOG_DRAIN: Logger = Logger::root( - logging::KubewardenDrain::new(), - o!("policy" => "sample-policy") - ); -} - #[no_mangle] pub extern "C" fn wapc_init() { register_function("validate", validate); @@ -31,40 +20,52 @@ pub extern "C" fn wapc_init() { fn validate(payload: &[u8]) -> CallResult { let validation_request: ValidationRequest = ValidationRequest::new(payload)?; - info!(LOG_DRAIN, "starting validation"); if validation_request.request.kind.kind != apicore::Pod::KIND { - warn!(LOG_DRAIN, "Policy validates Pods only. Accepting resource"; "kind" => &validation_request.request.kind.kind); return kubewarden::accept_request(); } - // TODO: you can unmarshal any Kubernetes API type you are interested in - match serde_json::from_value::(validation_request.request.object) { - Ok(pod) => { - // TODO: your logic goes here - if pod.metadata.name == Some("invalid-pod-name".to_string()) { - let pod_name = pod.metadata.name.unwrap(); - info!( - LOG_DRAIN, - "rejecting pod"; - "pod_name" => &pod_name - ); - kubewarden::reject_request( - Some(format!("pod name {} is not accepted", &pod_name)), - None, - None, - None, - ) - } else { - info!(LOG_DRAIN, "accepting resource"); - kubewarden::accept_request() - } - } - Err(_) => { - // TODO: handle as you wish - // We were forwarded a request we cannot unmarshal or - // understand, just accept it - warn!(LOG_DRAIN, "cannot unmarshal resource: this policy does not know how to evaluate this resource; accept it"); - kubewarden::accept_request() - } + let pod = serde_json::from_value::(validation_request.request.object)?; + + let podspec = pod.spec.clone().unwrap_or_default(); + let podspec_patched = enforce_ndots(&validation_request.settings, &podspec); + if podspec_patched != podspec { + let patched_pod = apicore::Pod { + spec: Some(podspec_patched), + ..pod + }; + return kubewarden::mutate_request(serde_json::to_value(&patched_pod)?); + } + + kubewarden::accept_request() +} + +fn enforce_ndots(settings: &Settings, podspec: &apicore::PodSpec) -> PodSpec { + let mut dns_options: Vec = podspec + .dns_config + .as_ref() + .and_then(|dns_config| dns_config.options.clone()) + .unwrap_or_default() + .iter() + .filter(|option| option.name != Some("ndots".to_string())) + .cloned() + .collect(); + dns_options.push(apicore::PodDNSConfigOption { + name: Some("ndots".to_string()), + value: Some(settings.ndots.to_string()), + }); + + PodSpec { + dns_config: Some(apicore::PodDNSConfig { + nameservers: podspec + .dns_config + .as_ref() + .and_then(|dns_config| dns_config.nameservers.clone()), + searches: podspec + .dns_config + .as_ref() + .and_then(|dns_config| dns_config.searches.clone()), + options: Some(dns_options), + }), + ..podspec.clone() } } @@ -73,64 +74,98 @@ mod tests { use super::*; use kubewarden_policy_sdk::test::Testcase; + use rstest::*; + + fn build_pod_dns_config(ndots: Option) -> apicore::PodDNSConfig { + let mut options = vec![apicore::PodDNSConfigOption { + name: Some("timeout".to_string()), + value: Some("5".to_string()), + }]; + + if let Some(ndots) = ndots { + options.push(apicore::PodDNSConfigOption { + name: Some("ndots".to_string()), + value: Some(ndots.to_string()), + }); + } - #[test] - fn accept_pod_with_valid_name() -> Result<(), ()> { - let request_file = "test_data/pod_creation.json"; - let tc = Testcase { - name: String::from("Valid name"), - fixture_file: String::from(request_file), - expected_validation_result: true, - settings: Settings::default(), - }; - - let res = tc.eval(validate).unwrap(); - assert!( - res.mutated_object.is_none(), - "Something mutated with test case: {}", - tc.name, - ); - - Ok(()) + apicore::PodDNSConfig { + nameservers: Some(vec!["1.1.1.1".to_string()]), + searches: Some(vec!["example.com".to_string()]), + options: Some(options), + } } - #[test] - fn reject_pod_with_invalid_name() -> Result<(), ()> { - let request_file = "test_data/pod_creation_invalid_name.json"; - let tc = Testcase { - name: String::from("Bad name"), - fixture_file: String::from(request_file), - expected_validation_result: false, - settings: Settings::default(), + #[rstest] + #[case::no_dns_config(None, apicore::PodDNSConfig { + options: Some(vec![apicore::PodDNSConfigOption{ + name: Some("ndots".to_string()), + value: Some("5".to_string()), + }]), + ..Default::default() + })] + #[case::no_dns_config_option_about_ndots( + Some(build_pod_dns_config(None)), + build_pod_dns_config(Some(5)) + )] + #[case::change_dns_config_option_about_ndots( + Some(build_pod_dns_config(Some(1))), + build_pod_dns_config(Some(5)) + )] + fn enforce_ndots_preserve_other_options( + #[case] dns_config: Option, + #[case] expected_dns_config: apicore::PodDNSConfig, + ) { + let settings = Settings { ndots: 5 }; + let podspec = PodSpec { + dns_config, + containers: vec![apicore::Container { + name: "nginx".to_string(), + image: Some("nginx".to_string()), + ..Default::default() + }], + ..Default::default() + }; + let expected_podspec = PodSpec { + dns_config: Some(expected_dns_config), + ..podspec.clone() }; - let res = tc.eval(validate).unwrap(); - assert!( - res.mutated_object.is_none(), - "Something mutated with test case: {}", - tc.name, + let podspec_patched = enforce_ndots(&settings, &podspec); + assert_eq!( + podspec_patched, expected_podspec, + "got: {:?} instead of {:?}", + podspec_patched, expected_podspec ); - - Ok(()) } - #[test] - fn accept_request_with_non_pod_resource() -> Result<(), ()> { - let request_file = "test_data/ingress_creation.json"; - let tc = Testcase { - name: String::from("Ingress creation"), - fixture_file: String::from(request_file), + #[rstest] + // Note: this test cares only about covering the switch statement of the resournce kind + #[case::change_pod("test_data/pod_without_ndots.json", true)] + #[case::do_not_change_pod("test_data/pod_with_5_ndots.json", false)] + fn test_validate(#[case] fixture: &str, #[case] expect_mutated_object: bool) { + let settings = Settings { ndots: 5 }; + + let test_case = Testcase { + name: "test".to_string(), + fixture_file: fixture.to_string(), expected_validation_result: true, - settings: Settings::default(), + settings: settings.clone(), }; - let res = tc.eval(validate).unwrap(); - assert!( - res.mutated_object.is_none(), - "Something mutated with test case: {}", - tc.name, - ); - - Ok(()) + let validation_response = test_case.eval(validate).expect("validation failed"); + if expect_mutated_object { + assert!(validation_response.mutated_object.is_some()); + let pod = + serde_json::from_value::(validation_response.mutated_object.unwrap()) + .expect("failed to parse mutated object"); + let dns_config_options = pod.spec.unwrap().dns_config.unwrap().options.unwrap(); + assert_eq!(dns_config_options.len(), 1); + let option = dns_config_options[0].clone(); + assert_eq!(option.name, Some("ndots".to_string())); + assert_eq!(option.value, Some(settings.ndots.to_string())); + } else { + assert!(validation_response.mutated_object.is_none()); + } } } diff --git a/src/settings.rs b/src/settings.rs index 8aeb9cd..dd81d76 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -1,34 +1,19 @@ -use crate::LOG_DRAIN; - use serde::{Deserialize, Serialize}; -use slog::info; // Describe the settings your policy expects when // loaded by the policy server. -#[derive(Serialize, Deserialize, Default, Debug)] -#[serde(default)] -pub(crate) struct Settings {} - -impl kubewarden::settings::Validatable for Settings { - fn validate(&self) -> Result<(), String> { - info!(LOG_DRAIN, "starting settings validation"); - - // TODO: perform settings validation if applies - Ok(()) - } +#[derive(Serialize, Deserialize, Default, Debug, Clone)] +pub(crate) struct Settings { + #[serde(default = "default_ndots")] + pub ndots: usize, } -#[cfg(test)] -mod tests { - use super::*; - - use kubewarden_policy_sdk::settings::Validatable; - - #[test] - fn validate_settings() -> Result<(), ()> { - let settings = Settings {}; +fn default_ndots() -> usize { + 1 +} - assert!(settings.validate().is_ok()); +impl kubewarden::settings::Validatable for Settings { + fn validate(&self) -> Result<(), String> { Ok(()) } } diff --git a/test_data/ingress_creation.json b/test_data/ingress_creation.json deleted file mode 100644 index ee8f0a1..0000000 --- a/test_data/ingress_creation.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "uid": "1299d386-525b-4032-98ae-1949f69f9cfc", - "kind": { - "group": "extensions", - "kind": "Ingress", - "version": "v1beta1" - }, - "resource": { - "group": "networking.k8s.io", - "version": "v1", - "resource": "ingresses" - }, - "operation": "CREATE", - "requestKind": { - "group": "networking.k8s.io", - "version": "v1", - "kind": "Ingress" - }, - "userInfo": { - "username": "alice", - "uid": "alice-uid", - "groups": [ - "system:authenticated" - ] - }, - "object": { - "metadata": { - "name": "prod" - }, - "spec": { - "tls": [ - { - "hosts": [ - "some-host.com" - ], - "secretName": "secret-name-tls" - } - ], - "rules": [ - { - "host": "some-host.com", - "http": { - "paths": [ - { - "path": "/", - "backend": { - "service": { - "name": "service", - "port": 443 - } - } - } - ] - } - } - ] - } - } -} diff --git a/test_data/pod_creation_invalid_name.json b/test_data/pod_with_5_ndots.json similarity index 84% rename from test_data/pod_creation_invalid_name.json rename to test_data/pod_with_5_ndots.json index ab13861..48d399d 100644 --- a/test_data/pod_creation_invalid_name.json +++ b/test_data/pod_with_5_ndots.json @@ -35,6 +35,14 @@ "name": "invalid-pod-name" }, "spec": { + "dnsConfig": { + "options": [ + { + "name": "ndots", + "value": "5" + } + ] + }, "containers": [ { "image": "nginx", diff --git a/test_data/pod_creation.json b/test_data/pod_without_ndots.json similarity index 100% rename from test_data/pod_creation.json rename to test_data/pod_without_ndots.json diff --git a/test_data/settings-5-ndots.yaml b/test_data/settings-5-ndots.yaml new file mode 100644 index 0000000..8735f30 --- /dev/null +++ b/test_data/settings-5-ndots.yaml @@ -0,0 +1 @@ +ndots: 5 From 1cda0d879de5bdd3f3a3bb52975af55c9e4424a9 Mon Sep 17 00:00:00 2001 From: Flavio Castelli Date: Tue, 1 Oct 2024 09:11:47 +0200 Subject: [PATCH 2/5] Update GHA * consume latest version * remove test action of the cargo-generate Signed-off-by: Flavio Castelli --- .github/workflows/cargo-generate-test.yml | 42 ----------------------- .github/workflows/release.yml | 11 +++--- .github/workflows/test.yml | 2 +- 3 files changed, 6 insertions(+), 49 deletions(-) delete mode 100644 .github/workflows/cargo-generate-test.yml diff --git a/.github/workflows/cargo-generate-test.yml b/.github/workflows/cargo-generate-test.yml deleted file mode 100644 index 2be9e6b..0000000 --- a/.github/workflows/cargo-generate-test.yml +++ /dev/null @@ -1,42 +0,0 @@ -name: Try to expand local template using cargo-generate -on: [push, pull_request] - -jobs: - build: - name: Render template and build - runs-on: ubuntu-latest - env: - PROJECT_NAME: demo - CARGO_GENERATE_VALUE_REGISTRY: ghcr.io - CARGO_GENERATE_VALUE_REGISTRY_MODULE_PATH_PREFIX: "kubewarden/policies" - steps: - - uses: actions/checkout@v4 - - uses: cargo-generate/cargo-generate-action@latest - with: - name: ${{ env.PROJECT_NAME }} - - name: Prepare Rust environment - uses: actions-rs/toolchain@v1 - with: - profile: minimal - toolchain: stable - target: wasm32-wasip1 - - name: Install kwctl - uses: kubewarden/github-actions/kwctl-installer@v3.1.11 - - name: Install bats - uses: mig4/setup-bats@v1.2.0 - with: - bats-version: 1.11.0 - - name: Move rendered template - run: | - # we need to move the generated project to a temp folder, away from the template project - # otherwise `cargo` runs would fail - # see https://github.com/rust-lang/cargo/issues/9922 - mv $PROJECT_NAME ${{ runner.temp }}/ - - name: Test - run: | - cd ${{ runner.temp }}/$PROJECT_NAME - make test - - name: e2e-tests - run: | - cd ${{ runner.temp }}/$PROJECT_NAME - make e2e-tests diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b4a5732..03c6623 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,18 +1,17 @@ on: push: branches: - - main - - master + - main + - master tags: - - 'v*' + - "v*" name: Release policy jobs: - test: name: run tests and linters - uses: kubewarden/github-actions/.github/workflows/reusable-test-policy-rust.yml@v3.1.0 + uses: kubewarden/github-actions/.github/workflows/reusable-test-policy-rust.yml@v3.3.5 release: needs: test @@ -24,6 +23,6 @@ jobs: # Required by cosign keyless signing id-token: write - uses: kubewarden/github-actions/.github/workflows/reusable-release-policy-rust.yml@v3.1.0 + uses: kubewarden/github-actions/.github/workflows/reusable-release-policy-rust.yml@v3.3.5 with: oci-target: ghcr.io/kubewarden/policies/pod-ndots diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cbd78bd..87f615c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -3,4 +3,4 @@ name: Continuous integration jobs: test: name: run tests and linters - uses: kubewarden/github-actions/.github/workflows/reusable-test-policy-rust.yml@v3.1.0 + uses: kubewarden/github-actions/.github/workflows/reusable-test-policy-rust.yml@v3.3.5 From e87007578d96dcac4568c0aac9901b4aad9bb635 Mon Sep 17 00:00:00 2001 From: Flavio Castelli Date: Tue, 1 Oct 2024 09:28:41 +0200 Subject: [PATCH 3/5] fix: prevent useless changes Do not alter the order of the DNS options Signed-off-by: Flavio Castelli --- src/lib.rs | 28 ++++++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index a8ff54b..232051d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -39,19 +39,35 @@ fn validate(payload: &[u8]) -> CallResult { } fn enforce_ndots(settings: &Settings, podspec: &apicore::PodSpec) -> PodSpec { + // preserve the order of the options to prevent needless updates let mut dns_options: Vec = podspec .dns_config .as_ref() .and_then(|dns_config| dns_config.options.clone()) .unwrap_or_default() .iter() - .filter(|option| option.name != Some("ndots".to_string())) - .cloned() + .map(|option| { + if option.name == Some("ndots".to_string()) { + apicore::PodDNSConfigOption { + name: Some("ndots".to_string()), + value: Some(settings.ndots.to_string()), + } + } else { + option.clone() + } + }) .collect(); - dns_options.push(apicore::PodDNSConfigOption { - name: Some("ndots".to_string()), - value: Some(settings.ndots.to_string()), - }); + + // ensure the option is added if it's not present + if dns_options + .iter() + .all(|option| option.name != Some("ndots".to_string())) + { + dns_options.push(apicore::PodDNSConfigOption { + name: Some("ndots".to_string()), + value: Some(settings.ndots.to_string()), + }); + } PodSpec { dns_config: Some(apicore::PodDNSConfig { From 9d6ddf77b7cb2a774cbb2febf7a2cf2a5c00662e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Cuadrado=20Juan?= Date: Tue, 1 Oct 2024 10:11:57 +0200 Subject: [PATCH 4/5] feat: Add questions-ui.yml MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Víctor Cuadrado Juan --- artifacthub-pkg.yml | 10 ++++++++++ questions-ui.yml | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/artifacthub-pkg.yml b/artifacthub-pkg.yml index 127c7ca..3ec8f8a 100644 --- a/artifacthub-pkg.yml +++ b/artifacthub-pkg.yml @@ -41,6 +41,16 @@ annotations: kubewarden/mutation: 'true' kubewarden/questions-ui: | questions: + - default: 1 + tooltip: Value for the Pod's spec.dnsConfig.options.ndots + description: >- + This policy enforces the DNS lookup configuration of a Pod to have the specified ndots value. + When no configuration is provided, the default value is 1. + group: Settings + label: ndots + required: false + type: int + variable: ndots kubewarden/resources: Pod kubewarden/rules: | - apiGroups: diff --git a/questions-ui.yml b/questions-ui.yml index 77bfa09..e97f145 100644 --- a/questions-ui.yml +++ b/questions-ui.yml @@ -1 +1,11 @@ questions: + - default: 1 + tooltip: Value for the Pod's spec.dnsConfig.options.ndots + description: >- + This policy enforces the DNS lookup configuration of a Pod to have the specified ndots value. + When no configuration is provided, the default value is 1. + group: Settings + label: ndots + required: false + type: int + variable: ndots From 07c5238b6ec9bfacacb35de6ba509be227f46f1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADctor=20Cuadrado=20Juan?= Date: Tue, 1 Oct 2024 10:12:10 +0200 Subject: [PATCH 5/5] fix: Use correct email MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Víctor Cuadrado Juan --- artifacthub-pkg.yml | 4 ++-- metadata.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/artifacthub-pkg.yml b/artifacthub-pkg.yml index 3ec8f8a..0687bfe 100644 --- a/artifacthub-pkg.yml +++ b/artifacthub-pkg.yml @@ -7,7 +7,7 @@ version: 0.1.0 name: pod-ndots displayName: Pod ndots -createdAt: 2024-10-01T06:58:50.339806282Z +createdAt: 2024-10-01T08:10:32.365438639Z description: Enforce a minimum value for the ndots option in the resolv.conf file of a Pod. license: Apache-2.0 homeURL: https://github.com/kubewarden/pod-ndots @@ -32,7 +32,7 @@ install: | ``` maintainers: - name: Kubewarden Developers - email: kubewarden@suse.de + email: cncf-kubewarden-maintainers@lists.cncf.io provider: name: kubewarden recommendations: diff --git a/metadata.yml b/metadata.yml index 834b6b4..7be2b81 100644 --- a/metadata.yml +++ b/metadata.yml @@ -20,7 +20,7 @@ annotations: # kubewarden specific: io.kubewarden.policy.title: pod-ndots io.kubewarden.policy.description: Enforce a minimum value for the ndots option in the resolv.conf file of a Pod. - io.kubewarden.policy.author: Kubewarden Developers + io.kubewarden.policy.author: Kubewarden Developers io.kubewarden.policy.url: https://github.com/kubewarden/pod-ndots io.kubewarden.policy.source: https://github.com/kubewarden/pod-ndots io.kubewarden.policy.license: Apache-2.0