diff --git a/poetry.lock b/poetry.lock
index 4e866872..ca5808a6 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
[[package]]
name = "alabaster"
@@ -157,33 +157,33 @@ lxml = ["lxml"]
[[package]]
name = "black"
-version = "24.1.1"
+version = "24.2.0"
description = "The uncompromising code formatter."
optional = false
python-versions = ">=3.8"
files = [
- {file = "black-24.1.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2588021038bd5ada078de606f2a804cadd0a3cc6a79cb3e9bb3a8bf581325a4c"},
- {file = "black-24.1.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1a95915c98d6e32ca43809d46d932e2abc5f1f7d582ffbe65a5b4d1588af7445"},
- {file = "black-24.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2fa6a0e965779c8f2afb286f9ef798df770ba2b6cee063c650b96adec22c056a"},
- {file = "black-24.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:5242ecd9e990aeb995b6d03dc3b2d112d4a78f2083e5a8e86d566340ae80fec4"},
- {file = "black-24.1.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fc1ec9aa6f4d98d022101e015261c056ddebe3da6a8ccfc2c792cbe0349d48b7"},
- {file = "black-24.1.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0269dfdea12442022e88043d2910429bed717b2d04523867a85dacce535916b8"},
- {file = "black-24.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3d64db762eae4a5ce04b6e3dd745dcca0fb9560eb931a5be97472e38652a161"},
- {file = "black-24.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:5d7b06ea8816cbd4becfe5f70accae953c53c0e53aa98730ceccb0395520ee5d"},
- {file = "black-24.1.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e2c8dfa14677f90d976f68e0c923947ae68fa3961d61ee30976c388adc0b02c8"},
- {file = "black-24.1.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a21725862d0e855ae05da1dd25e3825ed712eaaccef6b03017fe0853a01aa45e"},
- {file = "black-24.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:07204d078e25327aad9ed2c64790d681238686bce254c910de640c7cc4fc3aa6"},
- {file = "black-24.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:a83fe522d9698d8f9a101b860b1ee154c1d25f8a82ceb807d319f085b2627c5b"},
- {file = "black-24.1.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:08b34e85170d368c37ca7bf81cf67ac863c9d1963b2c1780c39102187ec8dd62"},
- {file = "black-24.1.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:7258c27115c1e3b5de9ac6c4f9957e3ee2c02c0b39222a24dc7aa03ba0e986f5"},
- {file = "black-24.1.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40657e1b78212d582a0edecafef133cf1dd02e6677f539b669db4746150d38f6"},
- {file = "black-24.1.1-cp38-cp38-win_amd64.whl", hash = "sha256:e298d588744efda02379521a19639ebcd314fba7a49be22136204d7ed1782717"},
- {file = "black-24.1.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:34afe9da5056aa123b8bfda1664bfe6fb4e9c6f311d8e4a6eb089da9a9173bf9"},
- {file = "black-24.1.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:854c06fb86fd854140f37fb24dbf10621f5dab9e3b0c29a690ba595e3d543024"},
- {file = "black-24.1.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3897ae5a21ca132efa219c029cce5e6bfc9c3d34ed7e892113d199c0b1b444a2"},
- {file = "black-24.1.1-cp39-cp39-win_amd64.whl", hash = "sha256:ecba2a15dfb2d97105be74bbfe5128bc5e9fa8477d8c46766505c1dda5883aac"},
- {file = "black-24.1.1-py3-none-any.whl", hash = "sha256:5cdc2e2195212208fbcae579b931407c1fa9997584f0a415421748aeafff1168"},
- {file = "black-24.1.1.tar.gz", hash = "sha256:48b5760dcbfe5cf97fd4fba23946681f3a81514c6ab8a45b50da67ac8fbc6c7b"},
+ {file = "black-24.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6981eae48b3b33399c8757036c7f5d48a535b962a7c2310d19361edeef64ce29"},
+ {file = "black-24.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d533d5e3259720fdbc1b37444491b024003e012c5173f7d06825a77508085430"},
+ {file = "black-24.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61a0391772490ddfb8a693c067df1ef5227257e72b0e4108482b8d41b5aee13f"},
+ {file = "black-24.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:992e451b04667116680cb88f63449267c13e1ad134f30087dec8527242e9862a"},
+ {file = "black-24.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:163baf4ef40e6897a2a9b83890e59141cc8c2a98f2dda5080dc15c00ee1e62cd"},
+ {file = "black-24.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e37c99f89929af50ffaf912454b3e3b47fd64109659026b678c091a4cd450fb2"},
+ {file = "black-24.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9de21bafcba9683853f6c96c2d515e364aee631b178eaa5145fc1c61a3cc92"},
+ {file = "black-24.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:9db528bccb9e8e20c08e716b3b09c6bdd64da0dd129b11e160bf082d4642ac23"},
+ {file = "black-24.2.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d84f29eb3ee44859052073b7636533ec995bd0f64e2fb43aeceefc70090e752b"},
+ {file = "black-24.2.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e08fb9a15c914b81dd734ddd7fb10513016e5ce7e6704bdd5e1251ceee51ac9"},
+ {file = "black-24.2.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:810d445ae6069ce64030c78ff6127cd9cd178a9ac3361435708b907d8a04c693"},
+ {file = "black-24.2.0-cp312-cp312-win_amd64.whl", hash = "sha256:ba15742a13de85e9b8f3239c8f807723991fbfae24bad92d34a2b12e81904982"},
+ {file = "black-24.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7e53a8c630f71db01b28cd9602a1ada68c937cbf2c333e6ed041390d6968faf4"},
+ {file = "black-24.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:93601c2deb321b4bad8f95df408e3fb3943d85012dddb6121336b8e24a0d1218"},
+ {file = "black-24.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0057f800de6acc4407fe75bb147b0c2b5cbb7c3ed110d3e5999cd01184d53b0"},
+ {file = "black-24.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:faf2ee02e6612577ba0181f4347bcbcf591eb122f7841ae5ba233d12c39dcb4d"},
+ {file = "black-24.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:057c3dc602eaa6fdc451069bd027a1b2635028b575a6c3acfd63193ced20d9c8"},
+ {file = "black-24.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:08654d0797e65f2423f850fc8e16a0ce50925f9337fb4a4a176a7aa4026e63f8"},
+ {file = "black-24.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ca610d29415ee1a30a3f30fab7a8f4144e9d34c89a235d81292a1edb2b55f540"},
+ {file = "black-24.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:4dd76e9468d5536abd40ffbc7a247f83b2324f0c050556d9c371c2b9a9a95e31"},
+ {file = "black-24.2.0-py3-none-any.whl", hash = "sha256:e8a6ae970537e67830776488bca52000eaa37fa63b9988e8c487458d9cd5ace6"},
+ {file = "black-24.2.0.tar.gz", hash = "sha256:bce4f25c27c3435e4dace4815bcb2008b87e167e3bf4ee47ccdc5ce906eb4894"},
]
[package.dependencies]
@@ -480,43 +480,43 @@ toml = ["tomli"]
[[package]]
name = "cryptography"
-version = "42.0.2"
+version = "42.0.3"
description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers."
optional = false
python-versions = ">=3.7"
files = [
- {file = "cryptography-42.0.2-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:701171f825dcab90969596ce2af253143b93b08f1a716d4b2a9d2db5084ef7be"},
- {file = "cryptography-42.0.2-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:61321672b3ac7aade25c40449ccedbc6db72c7f5f0fdf34def5e2f8b51ca530d"},
- {file = "cryptography-42.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea2c3ffb662fec8bbbfce5602e2c159ff097a4631d96235fcf0fb00e59e3ece4"},
- {file = "cryptography-42.0.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b15c678f27d66d247132cbf13df2f75255627bcc9b6a570f7d2fd08e8c081d2"},
- {file = "cryptography-42.0.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8e88bb9eafbf6a4014d55fb222e7360eef53e613215085e65a13290577394529"},
- {file = "cryptography-42.0.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a047682d324ba56e61b7ea7c7299d51e61fd3bca7dad2ccc39b72bd0118d60a1"},
- {file = "cryptography-42.0.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:36d4b7c4be6411f58f60d9ce555a73df8406d484ba12a63549c88bd64f7967f1"},
- {file = "cryptography-42.0.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:a00aee5d1b6c20620161984f8ab2ab69134466c51f58c052c11b076715e72929"},
- {file = "cryptography-42.0.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b97fe7d7991c25e6a31e5d5e795986b18fbbb3107b873d5f3ae6dc9a103278e9"},
- {file = "cryptography-42.0.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5fa82a26f92871eca593b53359c12ad7949772462f887c35edaf36f87953c0e2"},
- {file = "cryptography-42.0.2-cp37-abi3-win32.whl", hash = "sha256:4b063d3413f853e056161eb0c7724822a9740ad3caa24b8424d776cebf98e7ee"},
- {file = "cryptography-42.0.2-cp37-abi3-win_amd64.whl", hash = "sha256:841ec8af7a8491ac76ec5a9522226e287187a3107e12b7d686ad354bb78facee"},
- {file = "cryptography-42.0.2-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:55d1580e2d7e17f45d19d3b12098e352f3a37fe86d380bf45846ef257054b242"},
- {file = "cryptography-42.0.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28cb2c41f131a5758d6ba6a0504150d644054fd9f3203a1e8e8d7ac3aea7f73a"},
- {file = "cryptography-42.0.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9097a208875fc7bbeb1286d0125d90bdfed961f61f214d3f5be62cd4ed8a446"},
- {file = "cryptography-42.0.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:44c95c0e96b3cb628e8452ec060413a49002a247b2b9938989e23a2c8291fc90"},
- {file = "cryptography-42.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2f9f14185962e6a04ab32d1abe34eae8a9001569ee4edb64d2304bf0d65c53f3"},
- {file = "cryptography-42.0.2-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:09a77e5b2e8ca732a19a90c5bca2d124621a1edb5438c5daa2d2738bfeb02589"},
- {file = "cryptography-42.0.2-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad28cff53f60d99a928dfcf1e861e0b2ceb2bc1f08a074fdd601b314e1cc9e0a"},
- {file = "cryptography-42.0.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:130c0f77022b2b9c99d8cebcdd834d81705f61c68e91ddd614ce74c657f8b3ea"},
- {file = "cryptography-42.0.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:fa3dec4ba8fb6e662770b74f62f1a0c7d4e37e25b58b2bf2c1be4c95372b4a33"},
- {file = "cryptography-42.0.2-cp39-abi3-win32.whl", hash = "sha256:3dbd37e14ce795b4af61b89b037d4bc157f2cb23e676fa16932185a04dfbf635"},
- {file = "cryptography-42.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:8a06641fb07d4e8f6c7dda4fc3f8871d327803ab6542e33831c7ccfdcb4d0ad6"},
- {file = "cryptography-42.0.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:087887e55e0b9c8724cf05361357875adb5c20dec27e5816b653492980d20380"},
- {file = "cryptography-42.0.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a7ef8dd0bf2e1d0a27042b231a3baac6883cdd5557036f5e8df7139255feaac6"},
- {file = "cryptography-42.0.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4383b47f45b14459cab66048d384614019965ba6c1a1a141f11b5a551cace1b2"},
- {file = "cryptography-42.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:fbeb725c9dc799a574518109336acccaf1303c30d45c075c665c0793c2f79a7f"},
- {file = "cryptography-42.0.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:320948ab49883557a256eab46149df79435a22d2fefd6a66fe6946f1b9d9d008"},
- {file = "cryptography-42.0.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5ef9bc3d046ce83c4bbf4c25e1e0547b9c441c01d30922d812e887dc5f125c12"},
- {file = "cryptography-42.0.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:52ed9ebf8ac602385126c9a2fe951db36f2cb0c2538d22971487f89d0de4065a"},
- {file = "cryptography-42.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:141e2aa5ba100d3788c0ad7919b288f89d1fe015878b9659b307c9ef867d3a65"},
- {file = "cryptography-42.0.2.tar.gz", hash = "sha256:e0ec52ba3c7f1b7d813cd52649a5b3ef1fc0d433219dc8c93827c57eab6cf888"},
+ {file = "cryptography-42.0.3-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:de5086cd475d67113ccb6f9fae6d8fe3ac54a4f9238fd08bfdb07b03d791ff0a"},
+ {file = "cryptography-42.0.3-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:935cca25d35dda9e7bd46a24831dfd255307c55a07ff38fd1a92119cffc34857"},
+ {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20100c22b298c9eaebe4f0b9032ea97186ac2555f426c3e70670f2517989543b"},
+ {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2eb6368d5327d6455f20327fb6159b97538820355ec00f8cc9464d617caecead"},
+ {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:39d5c93e95bcbc4c06313fc6a500cee414ee39b616b55320c1904760ad686938"},
+ {file = "cryptography-42.0.3-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:3d96ea47ce6d0055d5b97e761d37b4e84195485cb5a38401be341fabf23bc32a"},
+ {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:d1998e545081da0ab276bcb4b33cce85f775adb86a516e8f55b3dac87f469548"},
+ {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93fbee08c48e63d5d1b39ab56fd3fdd02e6c2431c3da0f4edaf54954744c718f"},
+ {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:90147dad8c22d64b2ff7331f8d4cddfdc3ee93e4879796f837bdbb2a0b141e0c"},
+ {file = "cryptography-42.0.3-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:4dcab7c25e48fc09a73c3e463d09ac902a932a0f8d0c568238b3696d06bf377b"},
+ {file = "cryptography-42.0.3-cp37-abi3-win32.whl", hash = "sha256:1e935c2900fb53d31f491c0de04f41110351377be19d83d908c1fd502ae8daa5"},
+ {file = "cryptography-42.0.3-cp37-abi3-win_amd64.whl", hash = "sha256:762f3771ae40e111d78d77cbe9c1035e886ac04a234d3ee0856bf4ecb3749d54"},
+ {file = "cryptography-42.0.3-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:0d3ec384058b642f7fb7e7bff9664030011ed1af8f852540c76a1317a9dd0d20"},
+ {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:35772a6cffd1f59b85cb670f12faba05513446f80352fe811689b4e439b5d89e"},
+ {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:04859aa7f12c2b5f7e22d25198ddd537391f1695df7057c8700f71f26f47a129"},
+ {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c3d1f5a1d403a8e640fa0887e9f7087331abb3f33b0f2207d2cc7f213e4a864c"},
+ {file = "cryptography-42.0.3-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:df34312149b495d9d03492ce97471234fd9037aa5ba217c2a6ea890e9166f151"},
+ {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:de4ae486041878dc46e571a4c70ba337ed5233a1344c14a0790c4c4be4bbb8b4"},
+ {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:0fab2a5c479b360e5e0ea9f654bcebb535e3aa1e493a715b13244f4e07ea8eec"},
+ {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:25b09b73db78facdfd7dd0fa77a3f19e94896197c86e9f6dc16bce7b37a96504"},
+ {file = "cryptography-42.0.3-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d5cf11bc7f0b71fb71af26af396c83dfd3f6eed56d4b6ef95d57867bf1e4ba65"},
+ {file = "cryptography-42.0.3-cp39-abi3-win32.whl", hash = "sha256:0fea01527d4fb22ffe38cd98951c9044400f6eff4788cf52ae116e27d30a1ba3"},
+ {file = "cryptography-42.0.3-cp39-abi3-win_amd64.whl", hash = "sha256:2619487f37da18d6826e27854a7f9d4d013c51eafb066c80d09c63cf24505306"},
+ {file = "cryptography-42.0.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ead69ba488f806fe1b1b4050febafdbf206b81fa476126f3e16110c818bac396"},
+ {file = "cryptography-42.0.3-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:20180da1b508f4aefc101cebc14c57043a02b355d1a652b6e8e537967f1e1b46"},
+ {file = "cryptography-42.0.3-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:5fbf0f3f0fac7c089308bd771d2c6c7b7d53ae909dce1db52d8e921f6c19bb3a"},
+ {file = "cryptography-42.0.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c23f03cfd7d9826cdcbad7850de67e18b4654179e01fe9bc623d37c2638eb4ef"},
+ {file = "cryptography-42.0.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:db0480ffbfb1193ac4e1e88239f31314fe4c6cdcf9c0b8712b55414afbf80db4"},
+ {file = "cryptography-42.0.3-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:6c25e1e9c2ce682d01fc5e2dde6598f7313027343bd14f4049b82ad0402e52cd"},
+ {file = "cryptography-42.0.3-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:9541c69c62d7446539f2c1c06d7046aef822940d248fa4b8962ff0302862cc1f"},
+ {file = "cryptography-42.0.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1b797099d221df7cce5ff2a1d272761d1554ddf9a987d3e11f6459b38cd300fd"},
+ {file = "cryptography-42.0.3.tar.gz", hash = "sha256:069d2ce9be5526a44093a0991c450fe9906cdf069e0e7cd67d9dee49a62b9ebe"},
]
[package.dependencies]
@@ -624,13 +624,13 @@ files = [
[[package]]
name = "httpcore"
-version = "1.0.2"
+version = "1.0.3"
description = "A minimal low-level HTTP client."
optional = false
python-versions = ">=3.8"
files = [
- {file = "httpcore-1.0.2-py3-none-any.whl", hash = "sha256:096cc05bca73b8e459a1fc3dcf585148f63e534eae4339559c9b8a8d6399acc7"},
- {file = "httpcore-1.0.2.tar.gz", hash = "sha256:9fc092e4799b26174648e54b74ed5f683132a464e95643b226e00c2ed2fa6535"},
+ {file = "httpcore-1.0.3-py3-none-any.whl", hash = "sha256:9a6a501c3099307d9fd76ac244e08503427679b1e81ceb1d922485e2f2462ad2"},
+ {file = "httpcore-1.0.3.tar.gz", hash = "sha256:5c0f9546ad17dac4d0772b0808856eb616eb8b48ce94f49ed819fd6982a8a544"},
]
[package.dependencies]
@@ -641,7 +641,7 @@ h11 = ">=0.13,<0.15"
asyncio = ["anyio (>=4.0,<5.0)"]
http2 = ["h2 (>=3,<5)"]
socks = ["socksio (==1.*)"]
-trio = ["trio (>=0.22.0,<0.23.0)"]
+trio = ["trio (>=0.22.0,<0.24.0)"]
[[package]]
name = "httpx"
@@ -1201,7 +1201,6 @@ files = [
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
- {file = "PyYAML-6.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:326c013efe8048858a6d312ddd31d56e468118ad4cdeda36c719bf5bb6192290"},
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
@@ -1209,16 +1208,8 @@ files = [
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
- {file = "PyYAML-6.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e7d73685e87afe9f3b36c799222440d6cf362062f78be1013661b00c5c6f678b"},
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
- {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"},
- {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"},
- {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"},
- {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"},
- {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"},
- {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"},
- {file = "PyYAML-6.0.1-cp312-cp312-win_amd64.whl", hash = "sha256:0d3304d8c0adc42be59c5f8a4d9e3d7379e6955ad754aa9d6ab7a398b59dd1df"},
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
@@ -1235,7 +1226,6 @@ files = [
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
- {file = "PyYAML-6.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:49a183be227561de579b4a36efbb21b3eab9651dd81b1858589f796549873dd6"},
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
@@ -1243,7 +1233,6 @@ files = [
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
- {file = "PyYAML-6.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04ac92ad1925b2cff1db0cfebffb6ffc43457495c9b3c39d3fcae417d7125dc5"},
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
@@ -1309,28 +1298,28 @@ release = ["pip-tools (>=6.12.1)", "toml (>=0.10.2)", "twine (>=4.0.2)"]
[[package]]
name = "ruff"
-version = "0.2.1"
+version = "0.2.2"
description = "An extremely fast Python linter and code formatter, written in Rust."
optional = false
python-versions = ">=3.7"
files = [
- {file = "ruff-0.2.1-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:dd81b911d28925e7e8b323e8d06951554655021df8dd4ac3045d7212ac4ba080"},
- {file = "ruff-0.2.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:dc586724a95b7d980aa17f671e173df00f0a2eef23f8babbeee663229a938fec"},
- {file = "ruff-0.2.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c92db7101ef5bfc18e96777ed7bc7c822d545fa5977e90a585accac43d22f18a"},
- {file = "ruff-0.2.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:13471684694d41ae0f1e8e3a7497e14cd57ccb7dd72ae08d56a159d6c9c3e30e"},
- {file = "ruff-0.2.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a11567e20ea39d1f51aebd778685582d4c56ccb082c1161ffc10f79bebe6df35"},
- {file = "ruff-0.2.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:00a818e2db63659570403e44383ab03c529c2b9678ba4ba6c105af7854008105"},
- {file = "ruff-0.2.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:be60592f9d218b52f03384d1325efa9d3b41e4c4d55ea022cd548547cc42cd2b"},
- {file = "ruff-0.2.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fbd2288890b88e8aab4499e55148805b58ec711053588cc2f0196a44f6e3d855"},
- {file = "ruff-0.2.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3ef052283da7dec1987bba8d8733051c2325654641dfe5877a4022108098683"},
- {file = "ruff-0.2.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:7022d66366d6fded4ba3889f73cd791c2d5621b2ccf34befc752cb0df70f5fad"},
- {file = "ruff-0.2.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0a725823cb2a3f08ee743a534cb6935727d9e47409e4ad72c10a3faf042ad5ba"},
- {file = "ruff-0.2.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:0034d5b6323e6e8fe91b2a1e55b02d92d0b582d2953a2b37a67a2d7dedbb7acc"},
- {file = "ruff-0.2.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e5cb5526d69bb9143c2e4d2a115d08ffca3d8e0fddc84925a7b54931c96f5c02"},
- {file = "ruff-0.2.1-py3-none-win32.whl", hash = "sha256:6b95ac9ce49b4fb390634d46d6ece32ace3acdd52814671ccaf20b7f60adb232"},
- {file = "ruff-0.2.1-py3-none-win_amd64.whl", hash = "sha256:e3affdcbc2afb6f5bd0eb3130139ceedc5e3f28d206fe49f63073cb9e65988e0"},
- {file = "ruff-0.2.1-py3-none-win_arm64.whl", hash = "sha256:efababa8e12330aa94a53e90a81eb6e2d55f348bc2e71adbf17d9cad23c03ee6"},
- {file = "ruff-0.2.1.tar.gz", hash = "sha256:3b42b5d8677cd0c72b99fcaf068ffc62abb5a19e71b4a3b9cfa50658a0af02f1"},
+ {file = "ruff-0.2.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:0a9efb032855ffb3c21f6405751d5e147b0c6b631e3ca3f6b20f917572b97eb6"},
+ {file = "ruff-0.2.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:d450b7fbff85913f866a5384d8912710936e2b96da74541c82c1b458472ddb39"},
+ {file = "ruff-0.2.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ecd46e3106850a5c26aee114e562c329f9a1fbe9e4821b008c4404f64ff9ce73"},
+ {file = "ruff-0.2.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e22676a5b875bd72acd3d11d5fa9075d3a5f53b877fe7b4793e4673499318ba"},
+ {file = "ruff-0.2.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1695700d1e25a99d28f7a1636d85bafcc5030bba9d0578c0781ba1790dbcf51c"},
+ {file = "ruff-0.2.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:b0c232af3d0bd8f521806223723456ffebf8e323bd1e4e82b0befb20ba18388e"},
+ {file = "ruff-0.2.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f63d96494eeec2fc70d909393bcd76c69f35334cdbd9e20d089fb3f0640216ca"},
+ {file = "ruff-0.2.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6a61ea0ff048e06de273b2e45bd72629f470f5da8f71daf09fe481278b175001"},
+ {file = "ruff-0.2.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e1439c8f407e4f356470e54cdecdca1bd5439a0673792dbe34a2b0a551a2fe3"},
+ {file = "ruff-0.2.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:940de32dc8853eba0f67f7198b3e79bc6ba95c2edbfdfac2144c8235114d6726"},
+ {file = "ruff-0.2.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:0c126da55c38dd917621552ab430213bdb3273bb10ddb67bc4b761989210eb6e"},
+ {file = "ruff-0.2.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:3b65494f7e4bed2e74110dac1f0d17dc8e1f42faaa784e7c58a98e335ec83d7e"},
+ {file = "ruff-0.2.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:1ec49be4fe6ddac0503833f3ed8930528e26d1e60ad35c2446da372d16651ce9"},
+ {file = "ruff-0.2.2-py3-none-win32.whl", hash = "sha256:d920499b576f6c68295bc04e7b17b6544d9d05f196bb3aac4358792ef6f34325"},
+ {file = "ruff-0.2.2-py3-none-win_amd64.whl", hash = "sha256:cc9a91ae137d687f43a44c900e5d95e9617cb37d4c989e462980ba27039d239d"},
+ {file = "ruff-0.2.2-py3-none-win_arm64.whl", hash = "sha256:c9d15fc41e6054bfc7200478720570078f0b41c9ae4f010bcc16bd6f4d1aacdd"},
+ {file = "ruff-0.2.2.tar.gz", hash = "sha256:e62ed7f36b3068a30ba39193a14274cd706bc486fad521276458022f7bccb31d"},
]
[[package]]
@@ -1622,13 +1611,13 @@ files = [
[[package]]
name = "urllib3"
-version = "2.2.0"
+version = "2.2.1"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
python-versions = ">=3.8"
files = [
- {file = "urllib3-2.2.0-py3-none-any.whl", hash = "sha256:ce3711610ddce217e6d113a2732fafad960a03fd0318c91faa79481e35c11224"},
- {file = "urllib3-2.2.0.tar.gz", hash = "sha256:051d961ad0c62a94e50ecf1af379c3aba230c66c710493493560c0c223c49f20"},
+ {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"},
+ {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"},
]
[package.extras]
@@ -1655,4 +1644,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
[metadata]
lock-version = "2.0"
python-versions = "^3.9"
-content-hash = "e65a97eaa9895da266d4afbc23f519f977264a377b638170fd070f56b28aaeba"
+content-hash = "3f9a1be7a4d73f7c78aed7c385e49021458ee9a3056240d467a8396cb00bb174"
diff --git a/pyproject.toml b/pyproject.toml
index e5e760b1..ad9e8690 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -52,6 +52,7 @@ rope = ">=1.9.0"
furo = ">=2023.3.27"
sphinx-autobuild = ">=2021.3.14"
myst-parser = ">=2.0.0"
+lxml = ">=4.5.0"
[tool.black]
line-length = 80
diff --git a/scripts/README.md b/scripts/README.md
index ec5051e7..62a4a51f 100644
--- a/scripts/README.md
+++ b/scripts/README.md
@@ -54,7 +54,6 @@ This script can test different methods of the gmp API.
|`--showlog` | Include log messages in output.
| `--show-ports` | Include port of given vulnerable nvt in output.
| `--scanend` | Include timestamp of scan end in output.
-| `--autofp {0,1,2}` | Trust vendor security updates for automatic false positive filtering (`0=No`, `1=full match`, `2=partial`).
| `-e`, `--empty-as-unknown` | Respond with `UNKNOWN` on empty results.
| `-I MAX_RUNNING_INSTANCES`, `--max-running-instances MAX_RUNNING_INSTANCES` | Set the maximum simultaneous processes of check-gmp
| `--hostname [HOSTNAME]`
diff --git a/scripts/check-gmp.gmp.py b/scripts/check-gmp.gmp.py
index 6823fc83..f73bf6be 100644
--- a/scripts/check-gmp.gmp.py
+++ b/scripts/check-gmp.gmp.py
@@ -18,17 +18,18 @@
# pylint: disable=too-many-lines
+from dataclasses import dataclass
+from enum import Enum
import logging
import os
-import re
import signal
import sqlite3
import sys
import tempfile
from argparse import ArgumentParser, Namespace, RawTextHelpFormatter
from datetime import datetime, timedelta, tzinfo
-from decimal import Decimal
from pathlib import Path
+from typing import Any, Tuple
from gvm.protocols.gmp import Gmp
from lxml import etree
@@ -54,17 +55,30 @@
along with this program. If not, see .
"""
-NAGIOS_OK = 0
-NAGIOS_WARNING = 1
-NAGIOS_CRITICAL = 2
-NAGIOS_UNKNOWN = 3
+
+class NagiosStatus(Enum):
+ NAGIOS_OK = 0
+ NAGIOS_WARNING = 1
+ NAGIOS_CRITICAL = 2
+ NAGIOS_UNKNOWN = 3
+
+
+class GmpError(Enum):
+ GMP_OK = "GMP OK"
+ GMP_CRITICAL = "GMP CRITICAL"
+ GMP_UNKNOWN = "GMP UNKNOWN"
+
NAGIOS_MSG = ["OK", "WARNING", "CRITICAL", "UNKNOWN"]
MAX_RUNNING_INSTANCES = 10
-class InstanceManager:
+class ScriptError(Exception):
+ pass
+
+
+class ReportManager:
"""Class for managing instances of this plugin
All new reports will be cached in a sqlite database.
@@ -78,7 +92,7 @@ class InstanceManager:
and wait for continuation.
"""
- def __init__(self, path, parser):
+ def __init__(self, path: str) -> None:
"""Initialise the sqlite database.
Create it if it does not exist else connect to it.
@@ -87,21 +101,18 @@ def __init__(self, path, parser):
path (string): Path to the database.
"""
self.cursor = None
- self.con_db = None
- self.db = Path(path)
+ self.db = None
+ self.db_path = Path(path)
self.pid = os.getpid()
# Try to read file with information about cached reports
# First check whether the file exist or not
try:
- exist = self.db.is_file()
- logger.debug("DB file exist?: %s ", exist)
-
- if not exist:
- if not self.db.parent.is_dir():
- self.db.parent.mkdir(parents=True, exist_ok=True)
- else:
- self.db.touch()
+ if not self.db_path.is_file():
+ logger.debug("DB is not existing. Creating ...")
+ # create if not existing
+ self.db_path.parent.mkdir(parents=True, exist_ok=True)
+ self.db_path.touch(exist_ok=True)
# Connect to db
self.connect_db()
@@ -111,16 +122,14 @@ def __init__(self, path, parser):
host text,
scan_end text,
params_used text,
- report text
- )"""
+ report text)"""
)
self.cursor.execute(
"""CREATE TABLE Instance(
created_at text,
pid integer,
- pending integer default 0
- )"""
+ pending integer default 0)"""
)
logger.debug("Tables created")
@@ -128,42 +137,34 @@ def __init__(self, path, parser):
self.connect_db()
except PermissionError:
- parser.error(
- f"The selected temporary database file {self.db} or the parent "
- "dir has not the correct permissions."
+ raise ScriptError(
+ f"The selected temporary database file {self.db_path} or the"
+ " parent dir has not the correct permissions."
)
@staticmethod
- def _to_sql_bool(pending):
+ def _to_sql_bool(pending: bool) -> str:
"""Replace True/False with 1/0."""
return "1" if pending else "0"
- def connect_db(self):
+ def connect_db(self) -> None:
"""Connect to the database
Simply connect to the database at location
"""
try:
- logger.debug("connect db: %s", self.db)
- self.con_db = sqlite3.connect(str(self.db))
- self.cursor = self.con_db.cursor()
+ logger.debug("Connect to DB: %s", self.db_path)
+ self.db = sqlite3.connect(str(self.db_path))
+ self.cursor: sqlite3.Cursor = self.db.cursor()
logger.debug(sqlite3.sqlite_version)
except Exception as e: # pylint: disable=broad-except
logger.debug(e)
- def close_db(self):
+ def close_db(self) -> None:
"""Close database"""
- self.con_db.close()
+ self.db.close()
- def set_host(self, host):
- """Sets the host variable
-
- Arguments:
- host (string): Given ip or hostname of target.
- """
- self.host = host
-
- def is_old_report(self, last_scan_end, params_used):
+ def is_old_report(self, last_scan_end, params_used) -> bool:
"""Decide whether the current report is old or not
At first the last scanend and the params that were used are fetched
@@ -188,21 +189,23 @@ def is_old_report(self, last_scan_end, params_used):
"SELECT scan_end, params_used FROM Report WHERE host=?",
(self.host,),
)
- db_entry = self.cursor.fetchone()
+ (scan_end, old_params_used) = self.cursor.fetchone()
- logger.debug("%s %s", db_entry, last_scan_end)
+ logger.debug(
+ "DB last report: %s | New report: %s", scan_end, last_scan_end
+ )
- if not db_entry:
+ if not scan_end:
return True
else:
- old = parse_date(db_entry[0])
+ old = parse_date(scan_end)
new = parse_date(last_scan_end)
logger.debug(
"Old time (from db): %s\nNew time (from rp): %s", old, new
)
- if new <= old and params_used == db_entry[1]:
+ if new <= old and params_used == old_params_used:
return False
else:
# Report is newer. Delete old entry.
@@ -210,7 +213,7 @@ def is_old_report(self, last_scan_end, params_used):
self.delete_report()
return True
- def load_local_report(self):
+ def load_local_report(self) -> None:
"""Load report from local database
Select the report from the database according due the hostname or ip.
@@ -221,14 +224,14 @@ def load_local_report(self):
self.cursor.execute(
"SELECT report FROM Report WHERE host=?", (self.host,)
)
- db_entry = self.cursor.fetchone()
+ last_report = self.cursor.fetchone()
- if db_entry:
- return etree.fromstring(db_entry[0])
+ if last_report:
+ return etree.fromstring(last_report[0])
else:
logger.debug("Report from host %s is not in the db", self.host)
- def add_report(self, scan_end, params_used, report):
+ def add_report(self, scan_end, params_used, report) -> None:
"""Create new entry with the lxml report
Create a string from the lxml object and add it to the database.
@@ -251,16 +254,16 @@ def add_report(self, scan_end, params_used, report):
)
# Save the changes
- self.con_db.commit()
+ self.db.commit()
- def delete_report(self):
+ def delete_report(self) -> None:
"""Delete report from database"""
self.cursor.execute("DELETE FROM Report WHERE host=?", (self.host,))
# Save the changes
- self.con_db.commit()
+ self.db.commit()
- def delete_entry_with_ip(self, ip):
+ def delete_entry_with_ip(self, ip) -> None:
"""Delete report from database with given ip
Arguments:
@@ -268,11 +271,11 @@ def delete_entry_with_ip(self, ip):
"""
logger.debug("Delete entry with ip: %s", ip)
self.cursor.execute("DELETE FROM Report WHERE host=?", (ip,))
- self.con_db.isolation_level = None
+ self.db.isolation_level = None
self.cursor.execute("VACUUM")
- self.con_db.isolation_level = "" # see: https://github.com/CxAalto/gtfspy/commit/8d05c3c94a6d4ca3ed675d88af93def7d5053bfe # pylint: disable=line-too-long # noqa: E501
+ self.db.isolation_level = "" # see: https://github.com/CxAalto/gtfspy/commit/8d05c3c94a6d4ca3ed675d88af93def7d5053bfe # pylint: disable=line-too-long # noqa: E501
# Save the changes
- self.con_db.commit()
+ self.db.commit()
def delete_older_entries(self, days):
"""Delete reports from database older than given days
@@ -288,9 +291,9 @@ def delete_older_entries(self, days):
self.cursor.execute("VACUUM")
# Save the changes
- self.con_db.commit()
+ self.db.commit()
- def has_entries(self, pending):
+ def has_entries(self, pending: bool) -> Any:
"""Return number of instance entries
Arguments:
pending (bool): True for pending instances. False for running
@@ -399,10 +402,10 @@ def check_instances(self):
# Check if an pending entry is the same as this process
# If hostname
# date = datetime.now()
- # end_session('GMP PENDING: since %s' % date, NAGIOS_OK)
- # end_session('GMP RUNNING: since', NAGIOS_OK)
+ # end_session('GMP PENDING: since %s' % date, NagiosStatus.NAGIOS_OK)
+ # end_session('GMP RUNNING: since', NagiosStatus.NAGIOS_OK)
- def add_instance(self, pending):
+ def add_instance(self, pending) -> None:
"""Add new instance entry to database
Retrieve the current time in ISO 8601 format. Create a new entry with
@@ -420,9 +423,9 @@ def add_instance(self, pending):
)
# Save the changes
- self.con_db.commit()
+ self.db.commit()
- def get_oldest_pending_entries(self, number):
+ def get_oldest_pending_entries(self, number) -> list[Any]:
"""Return the oldest last entries of pending entries from database
Return:
@@ -436,7 +439,7 @@ def get_oldest_pending_entries(self, number):
)
return self.cursor.fetchall()
- def update_pending_status(self, date, pending):
+ def update_pending_status(self, date, pending) -> None:
"""Update pending status of instance
The date variable works as a primary key for the instance table.
@@ -452,9 +455,9 @@ def update_pending_status(self, date, pending):
)
# Save the changes
- self.con_db.commit()
+ self.db.commit()
- def delete_instance(self, pid=None):
+ def delete_instance(self, pid=None) -> None:
"""Delete instance from database
If a pid different from zero is given, then delete the entry with
@@ -471,13 +474,13 @@ def delete_instance(self, pid=None):
self.cursor.execute("DELETE FROM Instance WHERE pid=?", (pid,))
# Save the changes
- self.con_db.commit()
+ self.db.commit()
- def clean_orphaned_instances(self):
+ def clean_orphaned_instances(self) -> None:
"""Delete non existing instance entries
- This method check whether a pid exist on the os and if not then delete
- the orphaned entry from database.
+ This method checks whether a pid exists on the os and if not then
+ delete the orphaned entry from database.
"""
self.cursor.execute("SELECT pid FROM Instance")
@@ -487,7 +490,7 @@ def clean_orphaned_instances(self):
if not self.check_pid(pid[0]):
self.delete_instance(pid[0])
- def wake_instance(self):
+ def wake_instance(self) -> None:
"""Wake up a pending instance
This method is called at the end of any session from check_gmp.
@@ -520,7 +523,7 @@ def wake_instance(self):
self.update_pending_status(created_at, False)
self.start_process(pid)
- def start_process(self, pid):
+ def start_process(self, pid: int) -> None:
"""Continue a stopped process
Send a continue signal to the process with given pid
@@ -531,7 +534,7 @@ def start_process(self, pid):
logger.debug("Continue pid: %i", pid)
os.kill(pid, signal.SIGCONT)
- def stop_process(self, pid):
+ def stop_process(self, pid: int) -> None:
"""Stop a running process
Send a stop signal to the process with given pid
@@ -541,7 +544,7 @@ def stop_process(self, pid):
"""
os.kill(pid, signal.SIGSTOP)
- def check_pid(self, pid):
+ def check_pid(self, pid: int) -> bool:
"""Check for the existence of a process.
Arguments:
@@ -555,7 +558,7 @@ def check_pid(self, pid):
return True
-def ping(gmp, im):
+def ping(gmp: Gmp, report_manager: ReportManager):
"""Checks for connectivity
This function sends the get_version command and checks whether the status
@@ -565,12 +568,20 @@ def ping(gmp, im):
version_status = version.xpath("@status")
if "200" in version_status:
- end_session(im, "GMP OK: Ping successful", NAGIOS_OK)
+ end_session(
+ report_manager,
+ f"{GmpError.GMP_OK.value}: Ping successful",
+ NagiosStatus.NAGIOS_OK,
+ )
else:
- end_session(im, "GMP CRITICAL: Machine dead?", NAGIOS_CRITICAL)
+ end_session(
+ report_manager,
+ f"{GmpError.GMP_CRITICAL.value}: Machine dead?",
+ NagiosStatus.NAGIOS_CRITICAL,
+ )
-def status(gmp, im, script_args):
+def status(gmp: Gmp, report_manager: ReportManager, script_args: Namespace):
"""Returns the current status of a host
This functions return the current state of a host.
@@ -592,49 +603,58 @@ def status(gmp, im, script_args):
* Overrides
"""
params_used = (
- f"task={script_args.task} autofp={script_args.autofp} "
+ f"task={script_args.task}"
f"overrides={script_args.overrides} "
f"apply_overrides={script_args.apply_overrides}"
)
+ filter_string = f'permission=any owner=any name="{script_args.task}"'
+ print("Getting task with filter_string='{filter_string}'")
if script_args.task:
- task = gmp.get_tasks(
- filter_string=(
- "permission=any owner=any rows=1 " f'name="{script_args.task}"'
- )
- )
+ task: etree.Element = gmp.get_tasks(filter_string=filter_string)
if script_args.trend:
- trend = task.xpath("task/trend/text()")
+ trend: str = task.find("task/trend").text
+ # trend = task.xpath("task/trend/text()")
if not trend:
end_session(
- im, "GMP UNKNOWN: Trend is not available.", NAGIOS_UNKNOWN
+ report_manager,
+ f"{GmpError.GMP_OK.value}: Trend is not available.",
+ NagiosStatus.NAGIOS_UNKNOWN,
)
trend = trend[0]
if trend in ["up", "more"]:
end_session(
- im, f"GMP CRITICAL: Trend is {trend}.", NAGIOS_CRITICAL
+ report_manager,
+ f"{GmpError.GMP_CRITICAL.value}: Trend is {trend}.",
+ NagiosStatus.NAGIOS_CRITICAL,
)
elif trend in ["down", "same", "less"]:
- end_session(im, f"GMP OK: Trend is {trend}.", NAGIOS_OK)
+ end_session(
+ report_manager,
+ f"{GmpError.GMP_OK.value}: Trend is {trend}.",
+ NagiosStatus.NAGIOS_OK,
+ )
else:
end_session(
- im,
- f"GMP UNKNOWN: Trend is unknown: {trend}",
- NAGIOS_UNKNOWN,
+ report_manager,
+ f"{GmpError.GMP_OK.value}: Trend is unknown: {trend}",
+ NagiosStatus.NAGIOS_UNKNOWN,
)
else:
- last_report_id = task.xpath("task/last_report/report/@id")
+ last_report_id: str = task.xpath("task/last_report/report/@id")
if not last_report_id:
end_session(
- im, "GMP UNKNOWN: Report is not available", NAGIOS_UNKNOWN
+ report_manager,
+ f"{GmpError.GMP_OK.value}: Report is not available",
+ NagiosStatus.NAGIOS_UNKNOWN,
)
last_report_id = last_report_id[0]
- last_scan_end = task.xpath(
+ last_scan_end: str = task.xpath(
"task/last_report/report/scan_end/text()"
)
@@ -643,14 +663,14 @@ def status(gmp, im, script_args):
else:
last_scan_end = ""
- if im.is_old_report(last_scan_end, params_used):
+ if report_manager.is_old_report(last_scan_end, params_used):
host = script_args.hostaddress
full_report = gmp.get_report(
report_id=last_report_id,
filter_string=(
"sort-reverse=id result_hosts_only=1 min_cvss_base= "
- f"min_qod= levels=hmlgd autofp={script_args.autofp} "
+ f"min_qod= levels=hmlgd "
"notes=0 "
f"apply_overrides={script_args.apply_overrides} "
f"overrides={script_args.overrides} first=1 rows=-1 "
@@ -659,17 +679,25 @@ def status(gmp, im, script_args):
details=True,
)
- im.add_report(last_scan_end, params_used, full_report)
+ report_manager.add_report(
+ last_scan_end, params_used, full_report
+ )
logger.debug("Report added to db")
else:
- full_report = im.load_local_report()
+ full_report = report_manager.load_local_report()
filter_report(
- im, full_report.xpath("report/report")[0], script_args
+ report_manager,
+ full_report.xpath("report/report")[0],
+ script_args,
)
-def filter_report(im, report, script_args):
+def filter_report(
+ report_manager: ReportManager,
+ report: etree.ElementTree,
+ script_args: Namespace,
+):
"""Filter out the information in a report
This function filters the results of a given report.
@@ -680,108 +708,96 @@ def filter_report(im, report, script_args):
report_id = report.xpath("@id")
if report_id:
report_id = report_id[0]
- results = report.xpath("//results")
- if not results:
+ # results = report.xpath("//results")
+ results_element = report.find("report/results")
+ if not results_element:
end_session(
- im, "GMP UNKNOWN: Failed to get results list", NAGIOS_UNKNOWN
+ report_manager,
+ f"{GmpError.GMP_OK.value}: Failed to get results list",
+ NagiosStatus.NAGIOS_UNKNOWN,
)
- results = results[0]
- # Init variables
- any_found = False
- high_count = 0
- medium_count = 0
- low_count = 0
- log_count = 0
- error_count = 0
-
- nvts = {"high": [], "medium": [], "low": [], "log": []}
+ # results = results[0]
+ # results = results.xpath("result")
+ results = results_element.findall("result")
- all_results = results.xpath("result")
+ all_nvts = NVTs(
+ ports=script_args.show_ports,
+ log=script_args.show_log,
+ description=script_args.description,
+ dfn_certs=script_args.dfg,
+ )
- for result in all_results:
+ for result in results:
if script_args.hostaddress:
- host = result.xpath("host/text()")
+ host: etree.Element = result.find("host")
+ # host = result.xpath("host/text()")
if not host:
end_session(
- im,
- "GMP UNKNOWN: Failed to parse result host",
- NAGIOS_UNKNOWN,
+ report_manager,
+ f"{GmpError.GMP_OK.value}: Failed to parse result host",
+ NagiosStatus.NAGIOS_UNKNOWN,
)
if script_args.hostaddress != host[0]:
continue
- any_found = True
- threat = result.xpath("threat/text()")
+ threat = result.find("thread").text()
if not threat:
end_session(
- im,
- "GMP UNKNOWN: Failed to parse result threat.",
- NAGIOS_UNKNOWN,
+ report_manager,
+ f"{GmpError.GMP_OK.value}: Failed to parse result threat.",
+ NagiosStatus.NAGIOS_UNKNOWN,
)
-
- threat = threat[0]
- if threat in "High":
- high_count += 1
- if script_args.oid:
- nvts["high"].append(retrieve_nvt_data(result))
- elif threat in "Medium":
- medium_count += 1
- if script_args.oid:
- nvts["medium"].append(retrieve_nvt_data(result))
- elif threat in "Low":
- low_count += 1
- if script_args.oid:
- nvts["low"].append(retrieve_nvt_data(result))
- elif threat in "Log":
- log_count += 1
- if script_args.oid:
- nvts["log"].append(retrieve_nvt_data(result))
- else:
+ if threat not in [t.value for t in Threat]:
end_session(
- im,
- f"GMP UNKNOWN: Unknown result threat: {threat}",
- NAGIOS_UNKNOWN,
+ report_manager,
+ f"{GmpError.GMP_OK.value}: Unknown result threat: {threat}",
+ NagiosStatus.NAGIOS_UNKNOWN,
)
- errors = report.xpath("errors")
+ all_nvts.add(create_nvt(result=result))
+
+ errors = report.find("errors")
+ error_count = 0
if errors:
errors = errors[0]
if script_args.hostaddress:
for error in errors.xpath("error"):
- host = error.xpath("host/text()")
+ host: etree.Element = result.find("host")
+ # host = error.xpath("host/text()")
if script_args.hostaddress == host[0]:
error_count += 1
else:
- error_count = errors.xpath("count/text()")[0]
+ error_count = int(errors.find("count").text)
ret = 0
- if high_count > 0:
- ret = NAGIOS_CRITICAL
- elif medium_count > 0:
- ret = NAGIOS_WARNING
+ if all_nvts.count(threat=Threat.HIGH) > 0:
+ ret = NagiosStatus.NAGIOS_CRITICAL.value
+ elif all_nvts.count(threat=Threat.MEDIUM) > 0:
+ ret = NagiosStatus.NAGIOS_WARNING.value
+ # no vulnerabilities found (for the given host)
if script_args.empty_as_unknown and (
- not all_results or (not any_found and script_args.hostaddress)
+ not results or (not all_nvts.any and script_args.hostaddress)
):
- ret = NAGIOS_UNKNOWN
+ ret = NagiosStatus.NAGIOS_UNKNOWN.value
print(
f"GMP {NAGIOS_MSG[ret]}: "
- f"{str((high_count + medium_count + low_count))} "
- f"vulnerabilities found - High: {str(high_count)} "
- f"Medium: {str(medium_count)} Low: {str(low_count)}"
+ f"{all_nvts.all()} "
+ f"vulnerabilities found - High: {all_nvts.count(threat=Threat.HIGH)} "
+ f"Medium: {all_nvts.count(threat=Threat.MEDIUM)} Low: {all_nvts.count(threat=Threat.LOW)}"
)
- if not all_results:
+ if not results:
print("Report did not contain any vulnerabilities")
- elif not any_found and script_args.hostaddress:
+ elif not all_nvts.any and script_args.hostaddress:
print(
"Report did not contain vulnerabilities "
- f"for IP {script_args.hostaddress}"
+ f"for target Host {script_args.hostaddress}"
)
if int(error_count) > 0:
@@ -800,13 +816,7 @@ def filter_report(im, report, script_args):
)
if script_args.oid:
- print_nvt_data(
- nvts,
- show_log=script_args.showlog,
- show_ports=script_args.show_ports,
- descr=script_args.descr,
- dfn=script_args.dfn,
- )
+ all_nvts.print()
if script_args.scanend:
end = report.xpath("//end/text()")
@@ -822,86 +832,135 @@ def filter_report(im, report, script_args):
print_without_pipe(f"Task: {script_args.task}")
end_session(
- im,
- f"|High={str(high_count)} "
- f"Medium={str(medium_count)} "
- f"Low={str(low_count)}",
+ report_manager,
+ f"High: {all_nvts.count(threat=Threat.HIGH)} "
+ f"Medium: {all_nvts.count(threat=Threat.MEDIUM)} "
+ f"Low: {all_nvts.count(threat=Threat.LOW)}",
ret,
)
-def retrieve_nvt_data(result):
- """Retrieve the nvt data out of the result object
-
- This function parse the xml tree to find the important nvt data.
-
- Arguments:
- result (obj): Result as lxml ElementTree
+class Threat(Enum):
+ CRITICAL = "critical"
+ HIGH = "high"
+ MEDIUM = "medium"
+ LOW = "low"
+ LOG = "log"
+
+
+@dataclass
+class NVT:
+ oid: str = ""
+ name: str = ""
+ description: str = ""
+ port: str = ""
+ dfn_list: list[str] = []
+ threat: Threat = None
+
+ def as_tuple(self) -> Tuple[str, str, str, str, list[str]]:
+ return (self.oid, self.name, self.desc, self.port, self.dfn_list)
+
+ def print(
+ self,
+ ports: bool = False,
+ description: bool = False,
+ dfn_certs: bool = False,
+ ) -> None:
+ """Print this NVT"""
+ print_without_pipe(f"NVT: {self.oid} ({self.threat}) {self.name}")
+ if ports:
+ print_without_pipe(f"PORT: {self.port}")
+ if description:
+ print_without_pipe(f"DESCR: {self.description}")
+
+ if dfn_certs and self.dfn_list:
+ dfn_list = ", ".join(self.dfn_list)
+ print_without_pipe(f"DFN-CERT: {dfn_list}")
+
+
+@dataclass
+class NVTs:
+ ports: bool = False
+ log: bool = False
+ description: bool = False
+ dfn_certs: bool = False
+ nvts: dict[str, list[NVT]] = {
+ "high": [],
+ "medium": [],
+ "low": [],
+ "log": [],
+ }
+ any: bool = False
+
+ def add(self, nvt: NVT) -> None:
+ """Add a NVT"""
+ for threat, nvts in self.nvts.items():
+ if threat == nvt.threat:
+ nvts.append(nvt)
+ self.any = True
+
+ def print(self) -> None:
+ """Print the NVTs"""
+ for threat, nvts in self.nvts.items():
+ if threat == "Log" and not self.log:
+ # Skip log level NVTs
+ continue
+ if nvts:
+ for nvt in nvts:
+ nvt.print(
+ ports=self.ports,
+ description=self.description,
+ dfn_certs=self.dfn_cert,
+ )
- Returns:
- Tuple -- List with oid, name, desc, port and dfn
- """
- oid = result.xpath("nvt/@oid")
- name = result.xpath("nvt/name/text()")
- desc = result.xpath("description/text()")
- port = result.xpath("port/text()")
+ def count(self, threat: Threat) -> int:
+ return len(self.nvts.get(threat.value))
- if oid:
- oid = oid[0]
+ def all(self) -> int:
+ count = 0
+ for _, nvts in self.nvts.items():
+ count += len(nvts)
+ return count
- if name:
- name = name[0]
- if desc:
- desc = desc[0]
- else:
- desc = ""
+def create_nvt(result: etree.Element) -> NVT:
+ """Create an NVT instance from a result XML Element
- if port:
- port = port[0]
- else:
- port = ""
+ This function parses the result xml to find the important nvt data.
- certs = result.xpath("nvt/cert/cert_ref")
+ Arguments:
+ result: Result as lxml Element
- dfn_list = []
+ Returns:
+ NVT object containing oid, name, description, port and dfn-refs
+ """
+ nvt: etree.Element = result.find("nvt")
+ oid: str = nvt.get("id")
+ name: str = nvt.find("name").text
+ description: str = result.find("description").text
+ port: str = result.find("port").text
+ certs: etree.Element = nvt.findall("cert/cert_ref")
+ threat = result.find("threat").text
+
+ dfn_list: list[str] = []
for ref in certs:
- ref_type = ref.xpath("@type")[0]
- ref_id = ref.xpath("@id")[0]
- if ref_type in "DFN-CERT":
- dfn_list.append(ref_id)
+ if ref.get("type") == "DFN-CERT":
+ dfn_list.append(ref.get("id"))
- return (oid, name, desc, port, dfn_list)
+ return NVT(
+ oid=oid,
+ name=name,
+ description=description,
+ port=port,
+ dfn_list=dfn_list,
+ threat=threat,
+ )
-def print_nvt_data(
- nvts, show_log=False, show_ports=False, descr=False, dfn=False
+def end_session(
+ report_manager: ReportManager, msg: str, nagios_status: NagiosStatus
):
- """Print nvt data
-
- Prints for each nvt found in the array the relevant data
-
- Arguments:
- nvts (obj): Object holding all nvts
- """
- for key, nvt_data in nvts.items():
- if key == "log" and not show_log:
- continue
- for nvt in nvt_data:
- print_without_pipe(f"NVT: {nvt[0]} ({key}) {nvt[1]}")
- if show_ports:
- print_without_pipe(f"PORT: {nvt[3]}")
- if descr:
- print_without_pipe(f"DESCR: {nvt[2]}")
-
- if dfn and nvt[4]:
- dfn_list = ", ".join(nvt[4])
- if dfn_list:
- print_without_pipe(f"DFN-CERT: {dfn_list}")
-
-
-def end_session(im, msg, nagios_status):
"""End the session
Close the socket if open and print the last msg
@@ -913,15 +972,15 @@ def end_session(im, msg, nagios_status):
print(msg)
# Delete this instance
- im.delete_instance()
+ report_manager.delete_instance()
# Activate some waiting instances if possible
- im.wake_instance()
+ report_manager.wake_instance()
# Close the connection to database
- im.close_db()
+ report_manager.close_db()
- sys.exit(nagios_status)
+ sys.exit(nagios_status.value)
def print_without_pipe(msg):
@@ -933,102 +992,24 @@ def print_without_pipe(msg):
Arguments:
msg (string): Message to print
"""
- if "|" in msg:
- msg = msg.replace("|", "¦")
-
- print(msg)
-
-
-# ISO 8601 date time string parsing
-
-# Copyright (c) 2007 - 2015 Michael Twomey
-
-# Permission is hereby granted, free of charge, to any person obtaining a
-# copy of this software and associated documentation files (the
-# "Software"), to deal in the Software without restriction, including
-# without limitation the rights to use, copy, modify, merge, publish,
-# distribute, sublicense, and/or sell copies of the Software, and to
-# permit persons to whom the Software is furnished to do so, subject to
-# the following conditions:
-
-# The above copyright notice and this permission notice shall be included
-# in all copies or substantial portions of the Software.
-
-# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
-# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
-# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
-# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
-# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
-# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
-# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-__all__ = ["parse_date", "ParseError", "UTC"]
-
-# Adapted from http://delete.me.uk/2005/03/iso8601.html
-ISO8601_REGEX = re.compile(
- r"""
- (?P[0-9]{4})
- (
- (
- (-(?P[0-9]{1,2}))
- |
- (?P[0-9]{2})
- (?!$) # Don't allow YYYYMM
- )
- (
- (
- (-(?P[0-9]{1,2}))
- |
- (?P[0-9]{2})
- )
- (
- (
- (?P[ T])
- (?P[0-9]{2})
- (:{0,1}(?P[0-9]{2})){0,1}
- (
- :{0,1}(?P[0-9]{1,2})
- ([.,](?P[0-9]+)){0,1}
- ){0,1}
- (?P
- Z
- |
- (
- (?P[-+])
- (?P[0-9]{2})
- :{0,1}
- (?P[0-9]{2}){0,1}
- )
- ){0,1}
- ){0,1}
- )
- ){0,1} # YYYY-MM
- ){0,1} # YYYY only
- $
- """,
- re.VERBOSE,
-)
+ return msg.replace("|", "¦")
class ParseError(Exception):
"""Raised when there is a problem parsing a date string"""
-# Yoinked from python docs
-ZERO = timedelta(0)
-
-
class Utc(tzinfo):
"""UTC Timezone"""
def utcoffset(self, dt):
- return ZERO
+ return timedelta(0)
def tzname(self, dt):
return "UTC"
def dst(self, dt):
- return ZERO
+ return timedelta(0)
def __repr__(self):
return ""
@@ -1044,7 +1025,7 @@ def __init__(self, offset_hours, offset_minutes, name):
self.__offset_hours = offset_hours # Keep for later __getinitargs__
# Keep for later __getinitargs__
self.__offset_minutes = offset_minutes
- self.__offset = timedelta(hours=offset_hours, minutes=offset_minutes)
+ self.offset = timedelta(hours=offset_hours, minutes=offset_minutes)
self.__name = name
def __eq__(self, other):
@@ -1060,14 +1041,15 @@ def __eq__(self, other):
def __getinitargs__(self):
return (self.__offset_hours, self.__offset_minutes, self.__name)
- def utcoffset(self, dt):
- return self.__offset
+ # this shit is not even used ...
+ # def utcoffset(self, dt):
+ # return self.offset
- def tzname(self, dt):
- return self.__name
+ # def tzname(self, dt):
+ # return self.__name
def dst(self, dt):
- return ZERO
+ return timedelta(0)
def __repr__(self):
return f""
@@ -1083,7 +1065,7 @@ def to_int(
"""
- value = source_dict.get(key)
+ value = source_dict.get(key, "")
if value in [None, ""]:
value = default
if (value in ["", None]) and default_to_zero:
@@ -1116,70 +1098,21 @@ def parse_timezone(matches, default_timezone=UTC):
return FixedOffset(hours, minutes, description)
-def parse_date(datestring, default_timezone=UTC):
- """Parses ISO 8601 dates into datetime objects
-
- The timezone is parsed from the date string. However it is quite common to
- have dates without a timezone (not strictly correct). In this case the
- default timezone specified in default_timezone is used. This is UTC by
- default.
-
- Arguments
- datestring: The date to parse as a string
- default_timezone: A datetime tzinfo instance to use when no timezone
- is specified in the datestring. If this is set to
- None then a naive datetime object is returned.
- Returns:
- A datetime.datetime instance
- Raises:
- ParseError when there is a problem parsing the date or
- constructing the datetime instance.
-
- """
+def parse_date(datestring: str):
+ """will be removed."""
if not isinstance(datestring, str):
raise ParseError(f"Expecting a string {datestring}")
-
- match = ISO8601_REGEX.match(datestring)
- if not match:
- raise ParseError(f"Unable to parse date string {datestring}")
-
- groups = match.groupdict()
-
- tz = parse_timezone(groups, default_timezone=default_timezone)
-
- groups["second_fraction"] = int(
- Decimal(f"0.{groups['second_fraction'] or 0}") * Decimal("1000000.0")
- )
-
try:
- return datetime(
- year=to_int(groups, "year"),
- month=to_int(
- groups,
- "month",
- default=to_int(groups, "monthdash", required=False, default=1),
- ),
- day=to_int(
- groups,
- "day",
- default=to_int(groups, "daydash", required=False, default=1),
- ),
- hour=to_int(groups, "hour", default_to_zero=True),
- minute=to_int(groups, "minute", default_to_zero=True),
- second=to_int(groups, "second", default_to_zero=True),
- microsecond=groups["second_fraction"],
- tzinfo=tz,
- )
- except Exception as e:
- raise ParseError(e) from None
+ return datetime.fromisoformat(datestring)
+ except ValueError:
+ raise ParseError(f"Couldn't parse {datestring} to ISO format")
-def main(gmp: Gmp, args: Namespace) -> None:
- tmp_path = f"{tempfile.gettempdir()}/check_gmp/"
- tmp_path_db = tmp_path + "reports.db"
-
+def _parse_args(args: Namespace) -> Namespace:
prog = "check-gmp"
+ tmp_db = Path(tempfile.gettempdir()) / "check_gmp" / "reports.db"
+
parser = ArgumentParser(
prog=prog,
prefix_chars="-",
@@ -1207,12 +1140,14 @@ def main(gmp: Gmp, args: Namespace) -> None:
parser.add_argument(
"--cache",
nargs="?",
- default=tmp_path_db,
- help=f"Path to cache file. Default: {tmp_path_db}.",
+ default=tmp_db,
+ help=f"Path to cache file. Default: {tmp_db}.",
)
parser.add_argument(
- "--clean", action="store_true", help="Activate to clean the database."
+ "--clean",
+ action="store_true",
+ help="Activate to clean the database. Default: False",
)
parser.add_argument(
@@ -1236,75 +1171,72 @@ def main(gmp: Gmp, args: Namespace) -> None:
)
parser.add_argument(
- "--apply-overrides", action="store_true", help="Apply overrides."
+ "--apply-overrides",
+ action="store_true",
+ help="Apply overrides. Default: False",
)
parser.add_argument(
- "--overrides", action="store_true", help="Include overrides."
+ "--overrides",
+ action="store_true",
+ help="Include overrides. Default: False",
)
parser.add_argument(
"-d",
"--details",
action="store_true",
- help="Include connection details in output.",
+ help="Include connection details in output. Default: False",
)
parser.add_argument(
"-l",
"--report-link",
action="store_true",
- help="Include URL of report in output.",
+ help="Include URL of report in output. Default: False",
)
parser.add_argument(
"--dfn",
action="store_true",
- help="Include DFN-CERT IDs on vulnerabilities in output.",
+ help="Include DFN-CERT IDs on vulnerabilities in output. Default: False",
)
parser.add_argument(
"--oid",
action="store_true",
- help="Include OIDs of NVTs finding vulnerabilities in output.",
+ help="Include OIDs of NVTs finding vulnerabilities in output. Default: False",
)
parser.add_argument(
"--descr",
action="store_true",
- help="Include descriptions of NVTs finding vulnerabilities in output.",
+ help="Include descriptions of NVTs finding vulnerabilities in output. Default: False",
)
parser.add_argument(
- "--showlog", action="store_true", help="Include log messages in output."
+ "--showlog",
+ action="store_true",
+ help="Include log messages in output. Default: False",
)
parser.add_argument(
"--show-ports",
action="store_true",
- help="Include port of given vulnerable nvt in output.",
+ help="Include port of given vulnerable nvt in output. Default: False",
)
parser.add_argument(
"--scanend",
action="store_true",
- help="Include timestamp of scan end in output.",
- )
-
- parser.add_argument(
- "--autofp",
- type=int,
- choices=[0, 1, 2],
- default=0,
- help="Trust vendor security updates for automatic false positive"
- " filtering (0=No, 1=full match, 2=partial).",
+ help="Include timestamp of scan end in output. Default: False",
)
parser.add_argument(
"-e",
"--empty-as-unknown",
action="store_true",
- help="Respond with UNKNOWN on empty results.",
+ help="Respond with UNKNOWN on empty results. Default: False",
)
parser.add_argument(
@@ -1312,11 +1244,9 @@ def main(gmp: Gmp, args: Namespace) -> None:
"--max-running-instances",
default=10,
type=int,
- help="Set the maximum simultaneous processes of check-gmp",
+ help="Set the maximum simultaneous processes of check-gmp. Default: 10",
)
- parser.add_argument("--hostname", nargs="?", required=False)
-
group = parser.add_mutually_exclusive_group(required=False)
group.add_argument(
"--ping", action="store_true", help="Ping the gsm appliance."
@@ -1330,7 +1260,7 @@ def main(gmp: Gmp, args: Namespace) -> None:
group.add_argument(
"--days",
type=int,
- help="Delete database entries that are older than" " given days.",
+ help="Delete database entries that are older than given days.",
)
group.add_argument("--ip", help="Delete database entry for given ip.")
@@ -1344,15 +1274,27 @@ def main(gmp: Gmp, args: Namespace) -> None:
help="Report status by last report.",
)
- script_args = parser.parse_args(args.script_args)
+ return parser.parse_args(args.script_args)
+
+
+def main(gmp: Gmp, args: Namespace) -> None:
+ script_args = _parse_args(args=args)
aux_parser = ArgumentParser(
prefix_chars="-", formatter_class=RawTextHelpFormatter
)
aux_parser.add_argument("--hostname", nargs="?", required=False)
- gvm_tool_args, _ = aux_parser.parse_known_args(sys.argv)
- if "hostname" in gvm_tool_args:
- script_args.hostname = gvm_tool_args.hostname
+ aux_parser.add_argument(
+ "--gmp-username",
+ help="Username for GMP service (default: %(default)r)",
+ )
+ aux_parser.add_argument(
+ "--gmp-password",
+ help="Password for GMP service (default: %(default)r)",
+ )
+ main_args, _ = aux_parser.parse_known_args(sys.argv)
+ if main_args.hostname:
+ script_args.hostname = main_args.hostname
# Set the max running instances variable
if script_args.max_running_instances:
@@ -1362,36 +1304,38 @@ def main(gmp: Gmp, args: Namespace) -> None:
MAX_RUNNING_INSTANCES = script_args.max_running_instances
# Set the report manager
- if script_args.cache:
- tmp_path_db = script_args.cache
- im = InstanceManager(tmp_path_db, parser)
+ report_manager = ReportManager(script_args.cache)
# Check if command holds clean command
if script_args.clean:
if script_args.ip:
logger.info("Delete entry with ip %s", script_args.ip)
- im.delete_entry_with_ip(script_args.ip)
+ report_manager.delete_entry_with_ip(script_args.ip)
elif script_args.days:
logger.info("Delete entries older than %s days", script_args.days)
- im.delete_older_entries(script_args.days)
+ report_manager.delete_older_entries(script_args.days)
sys.exit(1)
# Set the host
- im.set_host(script_args.hostaddress)
+ report_manager.host = script_args.hostaddress
# Check if no more than 10 instances of check-gmp runs simultaneously
- im.check_instances()
+ report_manager.check_instances()
try:
gmp.get_version()
except Exception as e: # pylint: disable=broad-except
- end_session(im, f"GMP CRITICAL: {str(e)}", NAGIOS_CRITICAL)
+ end_session(
+ report_manager,
+ f"{GmpError.GMP_CRITICAL.value}: {str(e)}",
+ NagiosStatus.NAGIOS_CRITICAL,
+ )
if script_args.ping:
- ping(gmp, im)
+ ping(gmp, report_manager)
if "status" in script_args:
- status(gmp, im, script_args)
+ status(gmp, report_manager, script_args)
if __name__ == "__gmp__":
diff --git a/scripts/requirements.txt b/scripts/requirements.txt
index 937c4ab3..695f24c4 100644
--- a/scripts/requirements.txt
+++ b/scripts/requirements.txt
@@ -1,4 +1,6 @@
# required for monthly-report and monthly-report2 and certbund-report
terminaltables
# required for create-cve-report-from-json
-cpe
\ No newline at end of file
+cpe
+# required for check-gmp
+lxml
\ No newline at end of file