From 58f33cb5ed016e34b504cf264c84e2173e21b3a3 Mon Sep 17 00:00:00 2001 From: perp Date: Thu, 30 May 2024 03:41:53 +0100 Subject: [PATCH] First commit --- .gitignore | 1 + Cargo.lock | 1285 ++++++++++++++++++++++ Cargo.toml | 14 + LICENSE | 201 ++++ README.md | 78 ++ envoy-models/Cargo.toml | 14 + envoy-models/src/account/mod.rs | 2 + envoy-models/src/account/profile.rs | 10 + envoy-models/src/directory/mod.rs | 5 + envoy-models/src/directory/query.rs | 19 + envoy-models/src/directory/tags.rs | 15 + envoy-models/src/dns/domain.rs | 20 + envoy-models/src/dns/mod.rs | 2 + envoy-models/src/lib.rs | 42 + envoy-models/src/scanning/mod.rs | 5 + envoy-models/src/scanning/scan.rs | 10 + envoy-models/src/scanning/scans.rs | 20 + envoy-models/src/search/count.rs | 23 + envoy-models/src/search/host.rs | 95 ++ envoy-models/src/search/mod.rs | 8 + envoy-models/src/search/tokens.rs | 16 + envoy-models/src/status/info.rs | 23 + envoy-models/src/status/mod.rs | 2 + envoy-models/src/utility/http_headers.rs | 32 + envoy-models/src/utility/mod.rs | 2 + envoy/Cargo.toml | 14 + envoy/src/account/mod.rs | 1 + envoy/src/account/profile.rs | 19 + envoy/src/directory/mod.rs | 3 + envoy/src/directory/query.rs | 33 + envoy/src/directory/search.rs | 26 + envoy/src/directory/tags.rs | 24 + envoy/src/dns/domain.rs | 35 + envoy/src/dns/mod.rs | 3 + envoy/src/dns/resolve.rs | 24 + envoy/src/dns/reverse.rs | 21 + envoy/src/lib.rs | 78 ++ envoy/src/scanning/mod.rs | 4 + envoy/src/scanning/ports.rs | 17 + envoy/src/scanning/protocols.rs | 19 + envoy/src/scanning/scan.rs | 26 + envoy/src/scanning/scans.rs | 19 + envoy/src/search/count.rs | 26 + envoy/src/search/facets.rs | 17 + envoy/src/search/filters.rs | 17 + envoy/src/search/host.rs | 32 + envoy/src/search/mod.rs | 5 + envoy/src/search/tokens.rs | 21 + envoy/src/status/info.rs | 19 + envoy/src/status/mod.rs | 1 + envoy/src/utility/http_headers.rs | 19 + envoy/src/utility/mod.rs | 2 + envoy/src/utility/my_ip.rs | 17 + examples/Cargo.toml | 17 + examples/basic.rs | 29 + examples/proxy.rs | 25 + 56 files changed, 2557 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 README.md create mode 100644 envoy-models/Cargo.toml create mode 100644 envoy-models/src/account/mod.rs create mode 100644 envoy-models/src/account/profile.rs create mode 100644 envoy-models/src/directory/mod.rs create mode 100644 envoy-models/src/directory/query.rs create mode 100644 envoy-models/src/directory/tags.rs create mode 100644 envoy-models/src/dns/domain.rs create mode 100644 envoy-models/src/dns/mod.rs create mode 100644 envoy-models/src/lib.rs create mode 100644 envoy-models/src/scanning/mod.rs create mode 100644 envoy-models/src/scanning/scan.rs create mode 100644 envoy-models/src/scanning/scans.rs create mode 100644 envoy-models/src/search/count.rs create mode 100644 envoy-models/src/search/host.rs create mode 100644 envoy-models/src/search/mod.rs create mode 100644 envoy-models/src/search/tokens.rs create mode 100644 envoy-models/src/status/info.rs create mode 100644 envoy-models/src/status/mod.rs create mode 100644 envoy-models/src/utility/http_headers.rs create mode 100644 envoy-models/src/utility/mod.rs create mode 100644 envoy/Cargo.toml create mode 100644 envoy/src/account/mod.rs create mode 100644 envoy/src/account/profile.rs create mode 100644 envoy/src/directory/mod.rs create mode 100644 envoy/src/directory/query.rs create mode 100644 envoy/src/directory/search.rs create mode 100644 envoy/src/directory/tags.rs create mode 100644 envoy/src/dns/domain.rs create mode 100644 envoy/src/dns/mod.rs create mode 100644 envoy/src/dns/resolve.rs create mode 100644 envoy/src/dns/reverse.rs create mode 100644 envoy/src/lib.rs create mode 100644 envoy/src/scanning/mod.rs create mode 100644 envoy/src/scanning/ports.rs create mode 100644 envoy/src/scanning/protocols.rs create mode 100644 envoy/src/scanning/scan.rs create mode 100644 envoy/src/scanning/scans.rs create mode 100644 envoy/src/search/count.rs create mode 100644 envoy/src/search/facets.rs create mode 100644 envoy/src/search/filters.rs create mode 100644 envoy/src/search/host.rs create mode 100644 envoy/src/search/mod.rs create mode 100644 envoy/src/search/tokens.rs create mode 100644 envoy/src/status/info.rs create mode 100644 envoy/src/status/mod.rs create mode 100644 envoy/src/utility/http_headers.rs create mode 100644 envoy/src/utility/mod.rs create mode 100644 envoy/src/utility/my_ip.rs create mode 100644 examples/Cargo.toml create mode 100644 examples/basic.rs create mode 100644 examples/proxy.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..9ec117f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,1285 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "async-trait" +version = "0.1.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "autocfg" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" + +[[package]] +name = "backtrace" +version = "0.3.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bitflags" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bytes" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" + +[[package]] +name = "cc" +version = "1.0.97" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "099a5357d84c4c61eb35fc8eafa9a79a902c2f76911e5747ced4e032edd8d9b4" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "core-foundation" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" + +[[package]] +name = "either" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47c1c47d2f5964e29c61246e81db715514cd532db6b5116a25ea3c03d6780a2" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "envoy" +version = "1.7.0" +dependencies = [ + "async-trait", + "envoy-models", + "reqwest", + "serde", +] + +[[package]] +name = "envoy-models" +version = "1.7.0" +dependencies = [ + "reqwest", + "serde", + "serde_json", + "thiserror", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "examples" +version = "0.0.0" +dependencies = [ + "envoy", + "tokio", +] + +[[package]] +name = "fastrand" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + +[[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-channel" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" + +[[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-util" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "gimli" +version = "0.28.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" + +[[package]] +name = "h2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "816ec7294445779408f36fe57bc5b7fc1cf59664059096c65f905c1c61f58069" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "hyper" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-tls" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" +dependencies = [ + "bytes", + "http-body-util", + "hyper", + "hyper-util", + "native-tls", + "tokio", + "tokio-native-tls", + "tower-service", +] + +[[package]] +name = "hyper-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca38ef113da30126bbff9cd1705f9273e15d45498615d138b0c20279ac7a76aa" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "socket2", + "tokio", + "tower", + "tower-service", + "tracing", +] + +[[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.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "ipnet" +version = "2.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.154" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346" + +[[package]] +name = "linux-raw-sys" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" + +[[package]] +name = "log" +version = "0.4.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" + +[[package]] +name = "memchr" +version = "2.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" +dependencies = [ + "libc", + "wasi", + "windows-sys 0.48.0", +] + +[[package]] +name = "native-tls" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +dependencies = [ + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "num_cpus" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "object" +version = "0.32.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" + +[[package]] +name = "openssl" +version = "0.10.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[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 = "pkg-config" +version = "0.3.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" + +[[package]] +name = "proc-macro2" +version = "1.0.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "reqwest" +version = "0.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +dependencies = [ + "base64", + "bytes", + "encoding_rs", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-tls", + "hyper-util", + "ipnet", + "js-sys", + "log", + "mime", + "native-tls", + "once_cell", + "percent-encoding", + "pin-project-lite", + "rustls-pemfile", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "system-configuration", + "tokio", + "tokio-native-tls", + "tokio-socks", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustix" +version = "0.38.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +dependencies = [ + "bitflags 2.5.0", + "errno", + "libc", + "linux-raw-sys", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustls-pemfile" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29993a25686778eb88d4189742cd713c9bce943bc54251a33509dc63cbacf73d" +dependencies = [ + "base64", + "rustls-pki-types", +] + +[[package]] +name = "rustls-pki-types" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "beb461507cee2c2ff151784c52762cf4d9ff6a61f3e80968600ed24fa837fa54" + +[[package]] +name = "ryu" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" + +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + +[[package]] +name = "security-framework" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +dependencies = [ + "bitflags 2.5.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "serde" +version = "1.0.200" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddc6f9cc94d67c0e21aaf7eda3a010fd3af78ebf6e096aa6e2e13c79749cce4f" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.200" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "856f046b9400cee3c8c94ed572ecdb752444c24528c035cd35882aad6f492bcb" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.116" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e17db7126d17feb94eb3fad46bf1a96b034e8aacbc2e775fe81505f8b0b2813" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "syn" +version = "2.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys 0.52.0", +] + +[[package]] +name = "thiserror" +version = "1.0.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tinyvec" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +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 = "tokio" +version = "1.37.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1adbebffeca75fcfd058afa480fb6c0b81e165a0323f9c9d39c9697e37c46787" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "num_cpus", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.48.0", +] + +[[package]] +name = "tokio-macros" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + +[[package]] +name = "tokio-socks" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51165dfa029d2a65969413a6cc96f354b86b464498702f174a4efa13608fd8c0" +dependencies = [ + "either", + "futures-util", + "thiserror", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9cf6b47b3771c49ac75ad09a6162f53ad4b8088b76ac60e8ec1455b31a189fe1" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + +[[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.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "unicode-normalization" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.92" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" + +[[package]] +name = "web-sys" +version = "0.3.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", +] + +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + +[[package]] +name = "winreg" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" +dependencies = [ + "cfg-if", + "windows-sys 0.48.0", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..bcb0373 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[workspace] +resolver = "2" +members = [ + "envoy", + "envoy-models", + "examples" +] + +[workspace.package] +authors = ["perp"] +license = "Apache License 2.0" +repository = "https://git.supernets.org/perp/envoy" +description = "Shodan API wrapper made in Rust" +keywords = ["shodan", "shodan-api", "envoy"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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 + + http://www.apache.org/licenses/LICENSE-2.0 + + 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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..16c20f0 --- /dev/null +++ b/README.md @@ -0,0 +1,78 @@ +# Envoy +[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) + +Envoy is a Shodan API wrapper made in Rust + +## Examples +``` +cargo run --example basic +cargo run --example proxy +``` + +## API implementation + +[Shodan API documentation](https://developer.shodan.io/api) + +#### Search Methods +- [x] /shodan/host/{ip} +- [x] /shodan/host/count +- [ ] /shodan/host/search +- [x] /shodan/host/search/facets +- [x] /shodan/host/search/filters +- [x] /shodan/host/search/tokens + +#### On-Demand Scanning +- [x] /shodan/ports +- [x] /shodan/protocols +- [ ] /shodan/scan +- [ ] /shodan/scan/internet +- [x] /shodan/scan/{id} + +#### Network Alerts +- [ ] /shodan/alert +- [ ] /shodan/alert/{id}/info +- [ ] /shodan/alert/{id} +- [ ] /shodan/alert/info +- [ ] /shodan/alert/triggers +- [ ] /shodan/alert/{id}/trigger/{trigger} +- [ ] /shodan/alert/{id}/trigger/{trigger}/ignore/{service} +- [ ] /shodan/alert/{id}/notifier/{notifier_id} + +#### Notifiers +- [ ] /notifier +- [ ] /notifier/provider +- [ ] /notifier/{id} + +#### Directory Methods +- [x] /shodan/query +- [x] /shodan/query/search +- [x] /shodan/query/tags + +#### Bulk Data +- [ ] /shodan/data +- [ ] /shodan/data/{dataset} + +#### Manage Organization +- [ ] /org +- [ ] /org/member/{user} + +#### Account Methods +- [x] /account/profile + +#### DNS Methods +- [x] /dns/domain/{domain} +- [x] /dns/resolve +- [x] /dns/reverse + +#### Utility Methods +- [x] /tools/httpheaders +- [x] /tools/myip + +### API Status Methods +- [x] /api-info + +### Other +- [ ] Document examples for method + +## Disclaimer +###### Developers are not responsible for any misuse diff --git a/envoy-models/Cargo.toml b/envoy-models/Cargo.toml new file mode 100644 index 0000000..6d2293e --- /dev/null +++ b/envoy-models/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "envoy-models" +version = "1.7.0" +edition = "2021" +authors.workspace = true +license.workspace = true +repository.workspace = true +keywords.workspace = true + +[dependencies] +reqwest = { version = "0.12.4", features = ["json"] } +serde = { version = "1.0.200", features = ["derive"] } +serde_json = "1.0.116" +thiserror = "1.0.59" diff --git a/envoy-models/src/account/mod.rs b/envoy-models/src/account/mod.rs new file mode 100644 index 0000000..5d6e04d --- /dev/null +++ b/envoy-models/src/account/mod.rs @@ -0,0 +1,2 @@ +mod profile; +pub use profile::Profile; diff --git a/envoy-models/src/account/profile.rs b/envoy-models/src/account/profile.rs new file mode 100644 index 0000000..7c22b9f --- /dev/null +++ b/envoy-models/src/account/profile.rs @@ -0,0 +1,10 @@ +use serde::Deserialize; + +/// Profile response +#[derive(Debug, Deserialize)] +pub struct Profile { + pub member: bool, + pub credits: i64, + pub display_name: Option, + pub created: String, +} diff --git a/envoy-models/src/directory/mod.rs b/envoy-models/src/directory/mod.rs new file mode 100644 index 0000000..6d25784 --- /dev/null +++ b/envoy-models/src/directory/mod.rs @@ -0,0 +1,5 @@ +mod query; +pub use query::Query; + +mod tags; +pub use tags::Tags; diff --git a/envoy-models/src/directory/query.rs b/envoy-models/src/directory/query.rs new file mode 100644 index 0000000..a424a55 --- /dev/null +++ b/envoy-models/src/directory/query.rs @@ -0,0 +1,19 @@ +use serde::Deserialize; + +/// Query response +#[derive(Debug, Deserialize)] +pub struct Query { + pub matches: Vec, + pub total: i64, +} + +/// Matches response +#[derive(Debug, Deserialize)] +pub struct Matches { + pub votes: i64, + pub description: String, + pub tags: Vec, + pub timestamp: String, + pub title: String, + pub query: String, +} diff --git a/envoy-models/src/directory/tags.rs b/envoy-models/src/directory/tags.rs new file mode 100644 index 0000000..6a6b0c5 --- /dev/null +++ b/envoy-models/src/directory/tags.rs @@ -0,0 +1,15 @@ +use serde::Deserialize; + +/// Tags response +#[derive(Debug, Deserialize)] +pub struct Tags { + pub matches: Vec, + pub total: i64, +} + +/// Matches response +#[derive(Debug, Deserialize)] +pub struct Matches { + pub count: i64, + pub value: String, +} diff --git a/envoy-models/src/dns/domain.rs b/envoy-models/src/dns/domain.rs new file mode 100644 index 0000000..fd31a9b --- /dev/null +++ b/envoy-models/src/dns/domain.rs @@ -0,0 +1,20 @@ +use serde::Deserialize; + +/// Domain response +#[derive(Debug, Deserialize)] +pub struct Domain { + pub domain: String, + pub tags: Vec, + pub data: Vec, + pub subdomains: Vec, + pub more: bool, +} + +/// Data response +#[derive(Debug, Deserialize)] +pub struct Data { + pub subdomain: String, + pub r#type: String, + pub value: String, + pub last_seen: String, +} diff --git a/envoy-models/src/dns/mod.rs b/envoy-models/src/dns/mod.rs new file mode 100644 index 0000000..2cbadba --- /dev/null +++ b/envoy-models/src/dns/mod.rs @@ -0,0 +1,2 @@ +mod domain; +pub use domain::Domain; diff --git a/envoy-models/src/lib.rs b/envoy-models/src/lib.rs new file mode 100644 index 0000000..8b8475c --- /dev/null +++ b/envoy-models/src/lib.rs @@ -0,0 +1,42 @@ +use serde::Deserialize; + +pub mod account; +pub mod directory; +pub mod dns; +pub mod scanning; +pub mod search; +pub mod status; +pub mod utility; + +/// API error response +#[derive(Debug, Deserialize)] +pub struct ErrorResponse { + pub error: ErrorType, +} + +/// API error type +#[derive(Debug, Deserialize)] +pub enum ErrorType { + #[serde(rename(deserialize = "Invalid IP"))] + InvalidIP, + #[serde(rename(deserialize = "No information available for that IP."))] + UnknownIP, + #[serde(rename(deserialize = "Empty search query"))] + EmptyQuery, +} + +/// Client error +#[derive(Debug, thiserror::Error)] +pub enum Error { + /// API error + #[error("API returned an error: {0:#?}")] + API(ErrorResponse), + + /// Serde JSON error + #[error("Serde returned an error: {0}")] + Serialization(#[from] serde_json::Error), + + /// HTTP error + #[error("Reqwest returned an error: {0:#?}")] + HttpRequest(#[from] reqwest::Error), +} diff --git a/envoy-models/src/scanning/mod.rs b/envoy-models/src/scanning/mod.rs new file mode 100644 index 0000000..15da9d2 --- /dev/null +++ b/envoy-models/src/scanning/mod.rs @@ -0,0 +1,5 @@ +mod scan; +pub use scan::Scan; + +mod scans; +pub use scans::Scans; diff --git a/envoy-models/src/scanning/scan.rs b/envoy-models/src/scanning/scan.rs new file mode 100644 index 0000000..cccf1fa --- /dev/null +++ b/envoy-models/src/scanning/scan.rs @@ -0,0 +1,10 @@ +use serde::Deserialize; + +/// Scan response +#[derive(Debug, Deserialize)] +pub struct Scan { + pub count: i64, + pub status: String, + pub id: String, + pub created: String, +} diff --git a/envoy-models/src/scanning/scans.rs b/envoy-models/src/scanning/scans.rs new file mode 100644 index 0000000..127a76a --- /dev/null +++ b/envoy-models/src/scanning/scans.rs @@ -0,0 +1,20 @@ +use serde::Deserialize; + +/// Scans response +#[derive(Debug, Deserialize)] +pub struct Scans { + pub matches: Vec, + pub total: i64, +} + +/// Matches response +#[derive(Debug, Deserialize)] +pub struct Matches { + pub status: String, + pub created: String, + pub status_check: String, + pub credits_left: i64, + pub api_key: String, + pub id: String, + pub size: i64, +} diff --git a/envoy-models/src/search/count.rs b/envoy-models/src/search/count.rs new file mode 100644 index 0000000..3dafecb --- /dev/null +++ b/envoy-models/src/search/count.rs @@ -0,0 +1,23 @@ +use serde::Deserialize; + +/// Count response +#[derive(Debug, Deserialize)] +pub struct Count { + pub matches: Vec, + pub facets: Option, + pub total: i64, +} + +/// Facets response +#[derive(Debug, Deserialize)] +pub struct Facets { + pub org: Vec, + pub os: Vec, +} + +/// Facet response +#[derive(Debug, Deserialize)] +pub struct Facet { + pub count: i64, + pub value: String, +} diff --git a/envoy-models/src/search/host.rs b/envoy-models/src/search/host.rs new file mode 100644 index 0000000..bfe1d28 --- /dev/null +++ b/envoy-models/src/search/host.rs @@ -0,0 +1,95 @@ +use serde::Deserialize; + +/// Host response +#[derive(Debug, Deserialize)] +pub struct Host { + pub region_code: Option, + pub ip: i64, + pub postal_code: Option, + pub country_code: String, + pub city: Option, + pub dma_code: Option, + pub last_update: String, + pub latitude: f64, + pub tags: Vec, + pub area_code: Option, + pub country_name: String, + pub hostnames: Vec, + pub org: String, + pub data: Vec, + pub asn: String, + pub isp: String, + pub longitude: f64, + pub country_code3: Option, + pub domains: Vec, + pub ip_str: String, + pub os: Option, + pub ports: Vec, +} + +/// Data response +#[derive(Debug, Deserialize)] +pub struct Data { + #[serde(rename(deserialize = "_shodan"))] + pub shodan: Shodan, + pub hash: i64, + pub os: Option, + pub opts: Opts, + pub ip: i64, + pub isp: String, + pub port: i64, + pub hostnames: Vec, + pub location: Location, + pub dns: Option, + pub timestamp: String, + pub domains: Vec, + pub org: String, + pub data: String, + pub asn: String, + pub transport: String, + pub ip_str: String, +} + +/// Shodan response +#[derive(Debug, Deserialize)] +pub struct Shodan { + pub id: String, + pub options: Option, + pub ptr: Option, + pub module: String, + pub crawler: String, +} + +/// Options response +#[derive(Debug, Deserialize)] +pub struct Options {} + +/// Opts response +#[derive(Debug, Deserialize)] +pub struct Opts { + pub raw: Option, +} + +/// Location response +#[derive(Debug, Deserialize)] +pub struct Location { + pub city: Option, + pub region_code: Option, + pub area_code: Option, + pub longitude: f64, + pub country_code3: Option, + pub country_name: String, + pub postal_code: Option, + pub dma_code: Option, + pub country_code: String, + pub latitude: f64, +} + +/// DNS response +#[derive(Debug, Deserialize)] +pub struct Dns { + pub resolver_hostname: Option, + pub recursive: bool, + pub resolver_id: Option, + pub software: Option, +} diff --git a/envoy-models/src/search/mod.rs b/envoy-models/src/search/mod.rs new file mode 100644 index 0000000..7776461 --- /dev/null +++ b/envoy-models/src/search/mod.rs @@ -0,0 +1,8 @@ +mod count; +pub use count::Count; + +mod host; +pub use host::Host; + +mod tokens; +pub use tokens::Tokens; diff --git a/envoy-models/src/search/tokens.rs b/envoy-models/src/search/tokens.rs new file mode 100644 index 0000000..ce3d1d4 --- /dev/null +++ b/envoy-models/src/search/tokens.rs @@ -0,0 +1,16 @@ +use serde::Deserialize; + +/// Tokens response +#[derive(Debug, Deserialize)] +pub struct Tokens { + pub attributes: Attributes, + pub errors: Vec, + pub string: String, + pub filters: Vec, +} + +/// Attributes response +#[derive(Debug, Deserialize)] +pub struct Attributes { + pub ports: Vec, +} diff --git a/envoy-models/src/status/info.rs b/envoy-models/src/status/info.rs new file mode 100644 index 0000000..aab6445 --- /dev/null +++ b/envoy-models/src/status/info.rs @@ -0,0 +1,23 @@ +use serde::Deserialize; + +/// Info response +#[derive(Debug, Deserialize)] +pub struct Info { + pub scan_credits: i64, + pub usage_limits: UsageLimits, + pub plan: String, + pub https: bool, + pub unlocked: bool, + pub query_credits: i64, + pub monitored_ips: i64, + pub unlocked_left: i64, + pub telnet: bool, +} + +/// Usage limits response +#[derive(Debug, Deserialize)] +pub struct UsageLimits { + pub scan_credits: i64, + pub query_credits: i64, + pub monitored_ips: i64, +} diff --git a/envoy-models/src/status/mod.rs b/envoy-models/src/status/mod.rs new file mode 100644 index 0000000..9db04e2 --- /dev/null +++ b/envoy-models/src/status/mod.rs @@ -0,0 +1,2 @@ +mod info; +pub use info::Info; diff --git a/envoy-models/src/utility/http_headers.rs b/envoy-models/src/utility/http_headers.rs new file mode 100644 index 0000000..c0e64e0 --- /dev/null +++ b/envoy-models/src/utility/http_headers.rs @@ -0,0 +1,32 @@ +use serde::Deserialize; + +/// HTTP headers response +#[derive(Debug, Deserialize)] +pub struct HttpHeaders { + #[serde(rename(deserialize = "Content-Length"))] + pub content_length: String, + #[serde(rename(deserialize = "Cf-Visitor"))] + pub cf_visitor: String, + #[serde(rename(deserialize = "Accept-Encoding"))] + pub accept_encoding: String, + #[serde(rename(deserialize = "X-Forwarded-For"))] + pub x_forwarded_for: String, + #[serde(rename(deserialize = "Host"))] + pub host: String, + #[serde(rename(deserialize = "User-Agent"))] + pub user_agent: String, + #[serde(rename(deserialize = "Connection"))] + pub connection: String, + #[serde(rename(deserialize = "X-Forwarded-Proto"))] + pub x_forwarded_proto: String, + #[serde(rename(deserialize = "Accept"))] + pub accept: String, + #[serde(rename(deserialize = "Cdn-Loop"))] + pub cdn_loop: String, + #[serde(rename(deserialize = "Cf-Connecting-Ip"))] + pub cf_connecting_ip: String, + #[serde(rename(deserialize = "Cf-Ray"))] + pub cf_ray: String, + #[serde(rename(deserialize = "Content-Type"))] + pub content_type: String, +} diff --git a/envoy-models/src/utility/mod.rs b/envoy-models/src/utility/mod.rs new file mode 100644 index 0000000..6194319 --- /dev/null +++ b/envoy-models/src/utility/mod.rs @@ -0,0 +1,2 @@ +mod http_headers; +pub use http_headers::HttpHeaders; diff --git a/envoy/Cargo.toml b/envoy/Cargo.toml new file mode 100644 index 0000000..96f62db --- /dev/null +++ b/envoy/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "envoy" +version = "1.7.0" +edition = "2021" +authors.workspace = true +license.workspace = true +repository.workspace = true +keywords.workspace = true + +[dependencies] +async-trait = "0.1.80" +reqwest = { version = "0.12.4", default-features = false, features = ["json", "socks"] } +serde = { version = "1.0.200", features = ["derive"] } +envoy-models = { path = "../envoy-models/" } diff --git a/envoy/src/account/mod.rs b/envoy/src/account/mod.rs new file mode 100644 index 0000000..9155c64 --- /dev/null +++ b/envoy/src/account/mod.rs @@ -0,0 +1 @@ +pub(crate) mod profile; diff --git a/envoy/src/account/profile.rs b/envoy/src/account/profile.rs new file mode 100644 index 0000000..dac25be --- /dev/null +++ b/envoy/src/account/profile.rs @@ -0,0 +1,19 @@ +use envoy_models::account::Profile; + +use crate::prelude::*; + +impl Shodan { + /// Fetch account profile information + pub async fn fetch_profile(&self) -> Result { + Ok(self + .client + .get(format!("{}/account/profile", self.base_url)) + .query(&[("key", self.key.to_owned())]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/directory/mod.rs b/envoy/src/directory/mod.rs new file mode 100644 index 0000000..b5af108 --- /dev/null +++ b/envoy/src/directory/mod.rs @@ -0,0 +1,3 @@ +pub(crate) mod query; +pub(crate) mod search; +pub(crate) mod tags; diff --git a/envoy/src/directory/query.rs b/envoy/src/directory/query.rs new file mode 100644 index 0000000..744b6d3 --- /dev/null +++ b/envoy/src/directory/query.rs @@ -0,0 +1,33 @@ +use envoy_models::directory::Query; + +use crate::prelude::*; + +impl Shodan { + /// Fetch the saved queries + /// # Arguments + /// * `page` - Current page, contains 10 items (Default: 0) + /// * `sort` - Sort by property: votes or timestamp (Default: votes) + /// * `order` - Order by property: asc or desc (Default: desc) + pub async fn fetch_query( + &self, + page: Option, + sort: Option<&str>, + order: Option<&str>, + ) -> Result { + Ok(self + .client + .get(format!("{}/shodan/query", self.base_url)) + .query(&[ + ("key", self.key.to_owned()), + ("page", page.unwrap_or_default().to_string()), + ("sort", sort.unwrap_or("votes").to_string()), + ("order", order.unwrap_or("desc").to_string()), + ]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/directory/search.rs b/envoy/src/directory/search.rs new file mode 100644 index 0000000..7e10159 --- /dev/null +++ b/envoy/src/directory/search.rs @@ -0,0 +1,26 @@ +use envoy_models::directory::Query; + +use crate::prelude::*; + +impl Shodan { + /// Fetch a search query + /// # Arguments + /// * `query` - Query to search + /// * `page` - Current page, contains 10 items (Default: 0) + pub async fn fetch_search_query(&self, query: &str, page: Option) -> Result { + Ok(self + .client + .get(format!("{}/shodan/query/search", self.base_url)) + .query(&[ + ("key", self.key.to_owned()), + ("query", query.to_string()), + ("page", page.unwrap_or_default().to_string()), + ]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/directory/tags.rs b/envoy/src/directory/tags.rs new file mode 100644 index 0000000..4bdd324 --- /dev/null +++ b/envoy/src/directory/tags.rs @@ -0,0 +1,24 @@ +use envoy_models::directory::Tags; + +use crate::prelude::*; + +impl Shodan { + /// Fetch query tags + /// # Arguments + /// * `size` - Amount of tags (Default: 10) + pub async fn fetch_query_tags(&self, size: Option) -> Result { + Ok(self + .client + .get(format!("{}/shodan/query/tags", self.base_url)) + .query(&[ + ("key", self.key.to_owned()), + ("size", size.unwrap_or(10).to_string()), + ]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/dns/domain.rs b/envoy/src/dns/domain.rs new file mode 100644 index 0000000..d4a6b81 --- /dev/null +++ b/envoy/src/dns/domain.rs @@ -0,0 +1,35 @@ +use envoy_models::dns::Domain; + +use crate::prelude::*; + +impl Shodan { + /// Fetch subdomains and DNS entries for a domain + /// # Arguments + /// * `domain` - Domain to search + /// * `history` - Show old DNS records (Default: false) + /// * `type` - Type of DNS record: A, AAAA, CNAME, NS, SOA, MX, TXT (Default: A) + /// * `page` - Current page, contains 100 items (Default: 0) + pub async fn fetch_domain( + &self, + domain: &str, + history: Option, + r#type: Option<&str>, + page: Option, + ) -> Result { + Ok(self + .client + .get(format!("{}/dns/domain/{}", self.base_url, domain)) + .query(&[ + ("key", self.key.to_owned()), + ("history", history.unwrap_or(false).to_string()), + ("type", r#type.unwrap_or("A").to_string()), + ("page", page.unwrap_or_default().to_string()), + ]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/dns/mod.rs b/envoy/src/dns/mod.rs new file mode 100644 index 0000000..f14c4b6 --- /dev/null +++ b/envoy/src/dns/mod.rs @@ -0,0 +1,3 @@ +pub(crate) mod domain; +pub(crate) mod resolve; +pub(crate) mod reverse; diff --git a/envoy/src/dns/resolve.rs b/envoy/src/dns/resolve.rs new file mode 100644 index 0000000..9093ac2 --- /dev/null +++ b/envoy/src/dns/resolve.rs @@ -0,0 +1,24 @@ +use std::collections::HashMap; + +use crate::prelude::*; + +impl Shodan { + /// Fetch dns resolve information + /// # Arguments + /// * `hostnames` - Hostnames to search e.g google.com,bing.com + pub async fn fetch_dns_resolve(&self, hostnames: &str) -> Result> { + Ok(self + .client + .get(format!("{}/dns/resolve", self.base_url)) + .query(&[ + ("key", self.key.to_owned()), + ("hostnames", hostnames.to_string()), + ]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/dns/reverse.rs b/envoy/src/dns/reverse.rs new file mode 100644 index 0000000..1167536 --- /dev/null +++ b/envoy/src/dns/reverse.rs @@ -0,0 +1,21 @@ +use std::collections::HashMap; + +use crate::prelude::*; + +impl Shodan { + /// Fetch dns reverse information + /// # Arguments + /// * `ips` - IP addresses to search e.g 1.1.1.1,8.8.8.8 + pub async fn fetch_dns_reverse(&self, ips: &str) -> Result>> { + Ok(self + .client + .get(format!("{}/dns/reverse", self.base_url)) + .query(&[("key", self.key.to_owned()), ("ips", ips.to_string())]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/lib.rs b/envoy/src/lib.rs new file mode 100644 index 0000000..c1ed7a3 --- /dev/null +++ b/envoy/src/lib.rs @@ -0,0 +1,78 @@ +use async_trait::async_trait; +use envoy_models::Error; + +pub(crate) mod account; +pub(crate) mod directory; +pub(crate) mod dns; +pub(crate) mod scanning; +pub(crate) mod search; +pub(crate) mod status; +pub(crate) mod utility; + +pub(crate) mod prelude { + pub(crate) use crate::{ResponseExt, Result, Shodan}; +} + +/// Custom error Result type +pub type Result = std::result::Result; + +/// Base URL of Shodan API +pub const BASE_URL: &str = "https://api.shodan.io"; + +/// Handle response error +#[async_trait] +trait ResponseExt { + async fn process_error(self) -> Result + where + Self: Sized; +} + +/// Match response status code +/// and handle the error +#[async_trait] +impl ResponseExt for reqwest::Response { + async fn process_error(self) -> Result + where + Self: Sized, + { + match self.status().as_u16() { + 200 => Ok(self), + _ => Err(Error::API(self.json().await?)), + } + } +} + +/// Shodan client for interacting with the API +#[derive(Debug)] +pub struct Shodan { + key: String, + base_url: String, + client: reqwest::Client, +} + +impl Shodan { + /// Constructs a new `Shodan` client + pub fn new(key: &str) -> Self { + Self { + key: key.to_owned(), + base_url: BASE_URL.to_owned(), + client: reqwest::ClientBuilder::new() + .user_agent(concat!("Envoy", "/", env!("CARGO_PKG_VERSION"))) + .build() + .unwrap(), + } + } + + /// Constructs a new `Shodan` client with a proxy + pub fn new_with_proxy(key: &str, proxy: &str) -> Self { + Self { + key: key.to_owned(), + base_url: BASE_URL.to_owned(), + client: reqwest::ClientBuilder::new() + .user_agent(concat!("Envoy", "/", env!("CARGO_PKG_VERSION"))) + .proxy(reqwest::Proxy::all(proxy).expect("Could not connect to proxy")) + .build() + .unwrap(), + } + } +} diff --git a/envoy/src/scanning/mod.rs b/envoy/src/scanning/mod.rs new file mode 100644 index 0000000..a751489 --- /dev/null +++ b/envoy/src/scanning/mod.rs @@ -0,0 +1,4 @@ +pub(crate) mod ports; +pub(crate) mod protocols; +pub(crate) mod scan; +pub(crate) mod scans; diff --git a/envoy/src/scanning/ports.rs b/envoy/src/scanning/ports.rs new file mode 100644 index 0000000..14bacd0 --- /dev/null +++ b/envoy/src/scanning/ports.rs @@ -0,0 +1,17 @@ +use crate::prelude::*; + +impl Shodan { + /// Fetch a list of ports + pub async fn fetch_ports(&self) -> Result> { + Ok(self + .client + .get(format!("{}/shodan/ports", self.base_url)) + .query(&[("key", self.key.to_owned())]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/scanning/protocols.rs b/envoy/src/scanning/protocols.rs new file mode 100644 index 0000000..20a3152 --- /dev/null +++ b/envoy/src/scanning/protocols.rs @@ -0,0 +1,19 @@ +use std::collections::HashMap; + +use crate::prelude::*; + +impl Shodan { + /// Fetch a list of protocols + pub async fn fetch_protocols(&self) -> Result> { + Ok(self + .client + .get(format!("{}/shodan/protocols", self.base_url)) + .query(&[("key", self.key.to_owned())]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/scanning/scan.rs b/envoy/src/scanning/scan.rs new file mode 100644 index 0000000..f8c84e2 --- /dev/null +++ b/envoy/src/scanning/scan.rs @@ -0,0 +1,26 @@ +use envoy_models::scanning::Scan; + +use crate::prelude::*; + +impl Shodan { + /// Fetch a scan + /// # Arguments + /// * `id` - Scan ID + /// # Status + /// * SUBMITTING + /// * QUEUE + /// * PROCESSING + /// * DONE + pub async fn fetch_scan(&self, id: &str) -> Result { + Ok(self + .client + .get(format!("{}/shodan/scan/{}", self.base_url, id)) + .query(&[("key", self.key.to_owned())]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/scanning/scans.rs b/envoy/src/scanning/scans.rs new file mode 100644 index 0000000..d12007f --- /dev/null +++ b/envoy/src/scanning/scans.rs @@ -0,0 +1,19 @@ +use envoy_models::scanning::Scans; + +use crate::prelude::*; + +impl Shodan { + /// Fetch a list of scans + pub async fn fetch_scans(&self) -> Result { + Ok(self + .client + .get(format!("{}/shodan/scans", self.base_url)) + .query(&[("key", self.key.to_owned())]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/search/count.rs b/envoy/src/search/count.rs new file mode 100644 index 0000000..dc0d1bc --- /dev/null +++ b/envoy/src/search/count.rs @@ -0,0 +1,26 @@ +use envoy_models::search::Count; + +use crate::prelude::*; + +impl Shodan { + /// Fetch count of a query + /// # Arguments + /// * `query` - Query to search + /// * `facets` - Facets to search + pub async fn fetch_count(&self, query: &str, facets: Option<&str>) -> Result { + Ok(self + .client + .get(format!("{}/shodan/host/search/count", self.base_url)) + .query(&[ + ("key", self.key.to_owned()), + ("query", query.to_owned()), + ("facets", facets.unwrap_or_default().to_owned()), + ]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/search/facets.rs b/envoy/src/search/facets.rs new file mode 100644 index 0000000..720a477 --- /dev/null +++ b/envoy/src/search/facets.rs @@ -0,0 +1,17 @@ +use crate::prelude::*; + +impl Shodan { + /// Fetch a list of facets + pub async fn fetch_facets(&self) -> Result> { + Ok(self + .client + .get(format!("{}/shodan/host/search/facets", self.base_url)) + .query(&[("key", self.key.to_owned())]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/search/filters.rs b/envoy/src/search/filters.rs new file mode 100644 index 0000000..057ac03 --- /dev/null +++ b/envoy/src/search/filters.rs @@ -0,0 +1,17 @@ +use crate::prelude::*; + +impl Shodan { + /// Fetch a list of filters + pub async fn fetch_filters(&self) -> Result> { + Ok(self + .client + .get(format!("{}/shodan/host/search/filters", self.base_url)) + .query(&[("key", self.key.to_owned())]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/search/host.rs b/envoy/src/search/host.rs new file mode 100644 index 0000000..9a6715f --- /dev/null +++ b/envoy/src/search/host.rs @@ -0,0 +1,32 @@ +use envoy_models::search::Host; + +use crate::prelude::*; + +impl Shodan { + /// Fetch host information + /// # Arguments + /// * `ip` - Host IP address + /// * `history` - Show old records (Default: false) + /// * `minify` - Minify the response (Default: false) + pub async fn fetch_host( + &self, + ip: &str, + history: Option, + minify: Option, + ) -> Result { + Ok(self + .client + .get(format!("{}/shodan/host/{}", self.base_url, ip)) + .query(&[ + ("key", self.key.to_owned()), + ("history", history.unwrap_or_default().to_string()), + ("minify", minify.unwrap_or_default().to_string()), + ]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/search/mod.rs b/envoy/src/search/mod.rs new file mode 100644 index 0000000..06ba875 --- /dev/null +++ b/envoy/src/search/mod.rs @@ -0,0 +1,5 @@ +pub(crate) mod count; +pub(crate) mod facets; +pub(crate) mod filters; +pub(crate) mod host; +pub(crate) mod tokens; diff --git a/envoy/src/search/tokens.rs b/envoy/src/search/tokens.rs new file mode 100644 index 0000000..e82662c --- /dev/null +++ b/envoy/src/search/tokens.rs @@ -0,0 +1,21 @@ +use envoy_models::search::Tokens; + +use crate::prelude::*; + +impl Shodan { + /// Fetch a list of tokens + /// # Arguments + /// * `query` - Query to search + pub async fn fetch_tokens(&self, query: &str) -> Result { + Ok(self + .client + .get(format!("{}/shodan/host/search/tokens", self.base_url)) + .query(&[("key", self.key.to_owned()), ("query", query.to_owned())]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/status/info.rs b/envoy/src/status/info.rs new file mode 100644 index 0000000..523997e --- /dev/null +++ b/envoy/src/status/info.rs @@ -0,0 +1,19 @@ +use envoy_models::status::Info; + +use crate::prelude::*; + +impl Shodan { + /// Fetch plan information + pub async fn fetch_info(&self) -> Result { + Ok(self + .client + .get(format!("{}/api-info", self.base_url)) + .query(&[("key", self.key.to_owned())]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/status/mod.rs b/envoy/src/status/mod.rs new file mode 100644 index 0000000..ce878ad --- /dev/null +++ b/envoy/src/status/mod.rs @@ -0,0 +1 @@ +pub(crate) mod info; diff --git a/envoy/src/utility/http_headers.rs b/envoy/src/utility/http_headers.rs new file mode 100644 index 0000000..a733307 --- /dev/null +++ b/envoy/src/utility/http_headers.rs @@ -0,0 +1,19 @@ +use envoy_models::utility::HttpHeaders; + +use crate::prelude::*; + +impl Shodan { + /// Fetch HTTP headers + pub async fn fetch_http_headers(&self) -> Result { + Ok(self + .client + .get(format!("{}/tools/httpheaders", self.base_url)) + .query(&[("key", self.key.to_owned())]) + .send() + .await? + .process_error() + .await? + .json() + .await?) + } +} diff --git a/envoy/src/utility/mod.rs b/envoy/src/utility/mod.rs new file mode 100644 index 0000000..fe2f8a4 --- /dev/null +++ b/envoy/src/utility/mod.rs @@ -0,0 +1,2 @@ +pub(crate) mod http_headers; +pub(crate) mod my_ip; diff --git a/envoy/src/utility/my_ip.rs b/envoy/src/utility/my_ip.rs new file mode 100644 index 0000000..075e550 --- /dev/null +++ b/envoy/src/utility/my_ip.rs @@ -0,0 +1,17 @@ +use crate::prelude::*; + +impl Shodan { + /// Fetch my (your) current IP address + pub async fn fetch_my_ip(&self) -> Result { + Ok(self + .client + .get(format!("{}/tools/myip", self.base_url)) + .query(&[("key", self.key.to_owned())]) + .send() + .await? + .process_error() + .await? + .text() + .await?) + } +} diff --git a/examples/Cargo.toml b/examples/Cargo.toml new file mode 100644 index 0000000..7abb64d --- /dev/null +++ b/examples/Cargo.toml @@ -0,0 +1,17 @@ +[package] +name = "examples" +version = "0.0.0" +edition = "2021" +publish = false + +[dev-dependencies] +envoy = { path = "../envoy" } +tokio = { version = "1.37.0", features = ["rt-multi-thread", "macros"] } + +[[example]] +name = "basic" +path = "basic.rs" + +[[example]] +name = "proxy" +path = "proxy.rs" diff --git a/examples/basic.rs b/examples/basic.rs new file mode 100644 index 0000000..db89fa0 --- /dev/null +++ b/examples/basic.rs @@ -0,0 +1,29 @@ +use std::env; + +use envoy::Shodan; + +#[tokio::main] +async fn main() { + // CLI arguments + let args: Vec<_> = env::args().collect(); + + // Missing arguments + if args.len() < 2 { + panic!("Missing arguments"); + } + + // Create client + let shodan = Shodan::new(&args[1]); + + // Fetch profile + let profile = shodan.fetch_profile().await.unwrap(); + println!("{:#?}", profile); + + // Fetch information + let info = shodan.fetch_info().await.unwrap(); + println!("{:#?}", info); + + // Fetch tokens + let tokens = shodan.fetch_tokens("Raspbian port:22").await.unwrap(); + println!("{:#?}", tokens); +} diff --git a/examples/proxy.rs b/examples/proxy.rs new file mode 100644 index 0000000..b271cf9 --- /dev/null +++ b/examples/proxy.rs @@ -0,0 +1,25 @@ +use std::env; + +use envoy::Shodan; + +#[tokio::main] +async fn main() { + // CLI arguments + let args: Vec<_> = env::args().collect(); + + // Missing arguments + if args.len() < 2 { + panic!("Missing arguments"); + } + + // Create client + let shodan = Shodan::new_with_proxy(&args[1], &args[2]); + + // Fetch IP address + let myip = shodan.fetch_my_ip().await.unwrap(); + println!("{:#?}", myip); + + // Fetch headers + let headers = shodan.fetch_http_headers().await.unwrap(); + println!("{:#?}", headers); +}