From 5fa78b47fc6fe3794286c313d1377fadb9d2bfa1 Mon Sep 17 00:00:00 2001 From: axenna Date: Wed, 13 Sep 2023 19:28:44 -0400 Subject: [PATCH] [40] Build SMTP Integration For Threats Logging --- .cross/aarch64-unknown-linux-gnu.Dockerfile | 5 +- .cross/aarch64-unknown-linux-musl.Dockerfile | 5 +- .cross/riscv64gc-unknown-linux-gnu.Dockerfile | 5 +- .cross/x86_64-unknown-linux-gnu.Dockerfile | 2 +- .cross/x86_64-unknown-linux-musl.Dockerfile | 2 +- Cargo.lock | 352 ++++++++++++++++-- Cargo.toml | 5 +- crates/modules/smtp-notifier/Cargo.toml | 16 + crates/modules/smtp-notifier/README.md | 33 ++ crates/modules/smtp-notifier/src/lib.rs | 149 ++++++++ crates/validatron/src/reflection/adt.rs | 2 +- pulsar-install.sh | 2 +- src/lib.rs | 2 + 13 files changed, 538 insertions(+), 42 deletions(-) create mode 100644 crates/modules/smtp-notifier/Cargo.toml create mode 100644 crates/modules/smtp-notifier/README.md create mode 100644 crates/modules/smtp-notifier/src/lib.rs diff --git a/.cross/aarch64-unknown-linux-gnu.Dockerfile b/.cross/aarch64-unknown-linux-gnu.Dockerfile index 6944b98c..1c4619ea 100644 --- a/.cross/aarch64-unknown-linux-gnu.Dockerfile +++ b/.cross/aarch64-unknown-linux-gnu.Dockerfile @@ -1,6 +1,7 @@ FROM ghcr.io/cross-rs/aarch64-unknown-linux-gnu:main -RUN ln -snf /usr/share/zoneinfo/Europe/Rome /etc/localtime && echo Europe/Rome > /etc/timezone && \ - apt update && apt install -y lsb-release wget software-properties-common gnupg && \ +RUN dpkg --add-architecture arm64 && \ + ln -snf /usr/share/zoneinfo/Europe/Rome /etc/localtime && echo Europe/Rome > /etc/timezone && \ + apt update && apt install -y lsb-release wget software-properties-common gnupg libssl-dev:arm64 && \ wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 16 && \ ln -s /usr/bin/clang-16 /usr/bin/clang && \ ln -s /usr/bin/llvm-strip-16 /usr/bin/llvm-strip diff --git a/.cross/aarch64-unknown-linux-musl.Dockerfile b/.cross/aarch64-unknown-linux-musl.Dockerfile index c86ae1f0..a705d05d 100644 --- a/.cross/aarch64-unknown-linux-musl.Dockerfile +++ b/.cross/aarch64-unknown-linux-musl.Dockerfile @@ -1,6 +1,7 @@ FROM ghcr.io/cross-rs/aarch64-unknown-linux-musl:main -RUN ln -snf /usr/share/zoneinfo/Europe/Rome /etc/localtime && echo Europe/Rome > /etc/timezone && \ - apt update && apt install -y lsb-release wget software-properties-common gnupg && \ +RUN dpkg --ad-architecture arm64 && \ + ln -snf /usr/share/zoneinfo/Europe/Rome /etc/localtime && echo Europe/Rome > /etc/timezone && \ + apt update && apt install -y lsb-release wget software-properties-common gnupg libssl-dev:arm64 && \ wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 16 && \ ln -s /usr/bin/clang-16 /usr/bin/clang && \ ln -s /usr/bin/llvm-strip-16 /usr/bin/llvm-strip diff --git a/.cross/riscv64gc-unknown-linux-gnu.Dockerfile b/.cross/riscv64gc-unknown-linux-gnu.Dockerfile index 73d29a9f..52379274 100644 --- a/.cross/riscv64gc-unknown-linux-gnu.Dockerfile +++ b/.cross/riscv64gc-unknown-linux-gnu.Dockerfile @@ -1,6 +1,7 @@ FROM ghcr.io/cross-rs/riscv64gc-unknown-linux-gnu:main -RUN ln -snf /usr/share/zoneinfo/Europe/Rome /etc/localtime && echo Europe/Rome > /etc/timezone && \ - apt update && apt install -y lsb-release wget software-properties-common gnupg && \ +RUN dpkg --add--architecture risc64 && \ + ln -snf /usr/share/zoneinfo/Europe/Rome /etc/localtime && echo Europe/Rome > /etc/timezone && \ + apt update && apt install -y lsb-release wget software-properties-common gnupg libssl-dev:risc64 && \ wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 16 && \ ln -s /usr/bin/clang-16 /usr/bin/clang && \ ln -s /usr/bin/llvm-strip-16 /usr/bin/llvm-strip diff --git a/.cross/x86_64-unknown-linux-gnu.Dockerfile b/.cross/x86_64-unknown-linux-gnu.Dockerfile index 2da737eb..cbf16e49 100644 --- a/.cross/x86_64-unknown-linux-gnu.Dockerfile +++ b/.cross/x86_64-unknown-linux-gnu.Dockerfile @@ -1,6 +1,6 @@ FROM ghcr.io/cross-rs/x86_64-unknown-linux-gnu:main RUN ln -snf /usr/share/zoneinfo/Europe/Rome /etc/localtime && echo Europe/Rome > /etc/timezone && \ - apt update && apt install -y lsb-release wget software-properties-common gnupg && \ + apt update && apt install -y lsb-release wget software-properties-common gnupg libssl-dev && \ wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 16 && \ ln -s /usr/bin/clang-16 /usr/bin/clang && \ ln -s /usr/bin/llvm-strip-16 /usr/bin/llvm-strip diff --git a/.cross/x86_64-unknown-linux-musl.Dockerfile b/.cross/x86_64-unknown-linux-musl.Dockerfile index e22a923c..ad5fefc9 100644 --- a/.cross/x86_64-unknown-linux-musl.Dockerfile +++ b/.cross/x86_64-unknown-linux-musl.Dockerfile @@ -1,6 +1,6 @@ FROM ghcr.io/cross-rs/x86_64-unknown-linux-musl:main RUN ln -snf /usr/share/zoneinfo/Europe/Rome /etc/localtime && echo Europe/Rome > /etc/timezone && \ - apt update && apt install -y lsb-release wget software-properties-common gnupg && \ + apt update && apt install -y lsb-release wget software-properties-common gnupg libssl-dev && \ wget https://apt.llvm.org/llvm.sh && chmod +x llvm.sh && ./llvm.sh 16 && \ ln -s /usr/bin/clang-16 /usr/bin/clang && \ ln -s /usr/bin/llvm-strip-16 /usr/bin/llvm-strip diff --git a/Cargo.lock b/Cargo.lock index a6c5918f..62096c7b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -210,6 +210,12 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5" +[[package]] +name = "base64" +version = "0.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" + [[package]] name = "bit-set" version = "0.5.3" @@ -306,9 +312,12 @@ checksum = "dfb24e866b15a1af2a1b663f10c6b6b8f397a84aadb828f12e5b289ec23a3a3c" [[package]] name = "cc" -version = "1.0.78" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a20104e2335ce8a659d6dd92a51a767a0c062599c73b343fd152cb401e828c3d" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -372,7 +381,7 @@ dependencies = [ "heck 0.4.0", "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.33", ] [[package]] @@ -418,6 +427,22 @@ dependencies = [ "version_check", ] +[[package]] +name = "core-foundation" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + [[package]] name = "cpufeatures" version = "0.2.5" @@ -541,6 +566,22 @@ version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" +[[package]] +name = "email-encoding" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbfb21b9878cf7a348dcb8559109aabc0ec40d69924bd706fa5149846c4fef75" +dependencies = [ + "base64 0.21.4", + "memchr", +] + +[[package]] +name = "email_address" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2153bd83ebc09db15bcbdc3e2194d901804952e3dc96967e1cd3b0c5c32d112" + [[package]] name = "ena" version = "0.14.2" @@ -614,6 +655,15 @@ dependencies = [ "libc", ] +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "file-system-monitor" version = "0.6.0" @@ -638,11 +688,26 @@ 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.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -916,6 +981,16 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "idna" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "indexmap" version = "1.9.2" @@ -926,6 +1001,15 @@ dependencies = [ "hashbrown 0.12.3", ] +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "io-lifetimes" version = "1.0.4" @@ -1000,11 +1084,36 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lettre" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76bd09637ae3ec7bd605b8e135e757980b3968430ff2b1a4a94fb7769e50166d" +dependencies = [ + "async-trait", + "base64 0.21.4", + "email-encoding", + "email_address", + "fastrand", + "futures-io", + "futures-util", + "httpdate", + "idna 0.3.0", + "mime", + "native-tls", + "nom", + "once_cell", + "quoted_printable", + "socket2", + "tokio", + "tokio-native-tls", +] + [[package]] name = "libc" -version = "0.2.139" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "libtest-mimic" @@ -1086,6 +1195,12 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "mio" version = "0.8.5" @@ -1098,6 +1213,24 @@ dependencies = [ "windows-sys 0.42.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 = "network-monitor" version = "0.6.0" @@ -1143,6 +1276,16 @@ dependencies = [ "static_assertions", ] +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + [[package]] name = "num-integer" version = "0.1.45" @@ -1183,9 +1326,63 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.0" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "openssl" +version = "0.10.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" +dependencies = [ + "bitflags 2.2.1", + "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 2.0.33", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-src" +version = "300.1.3+3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd2c101a165fff9935e34def4669595ab1c7847943c42be86e21503e482be107" +dependencies = [ + "cc", +] + +[[package]] +name = "openssl-sys" +version = "0.9.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" +dependencies = [ + "cc", + "libc", + "openssl-src", + "pkg-config", + "vcpkg", +] [[package]] name = "ordered-multimap" @@ -1215,16 +1412,16 @@ checksum = "ba1ef8814b5c993410bb3adfad7a5ed269563e4a2f90c41f5d85be7fb47133bf" dependencies = [ "cfg-if", "libc", - "redox_syscall", + "redox_syscall 0.2.16", "smallvec", "windows-sys 0.42.0", ] [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "petgraph" @@ -1277,6 +1474,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkg-config" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" + [[package]] name = "ppv-lite86" version = "0.2.17" @@ -1291,9 +1494,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] @@ -1349,6 +1552,7 @@ dependencies = [ "rust-ini", "semver", "serde", + "smtp-notifier", "tokio", ] @@ -1376,13 +1580,19 @@ checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ "proc-macro2", ] +[[package]] +name = "quoted_printable" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a3866219251662ec3b26fc217e3e05bf9c4f84325234dfb96bf0bf840889e49" + [[package]] name = "rand" version = "0.8.5" @@ -1422,6 +1632,15 @@ dependencies = [ "bitflags 1.3.2", ] +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "redox_users" version = "0.4.3" @@ -1429,7 +1648,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", - "redox_syscall", + "redox_syscall 0.2.16", "thiserror", ] @@ -1517,12 +1736,44 @@ version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b4b9743ed687d4b4bcedf9ff5eaa7398495ae14e61cba0a295704edbc7decde" +[[package]] +name = "schannel" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +dependencies = [ + "windows-sys 0.48.0", +] + [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "security-framework" +version = "2.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "semver" version = "1.0.16" @@ -1534,22 +1785,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.160" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.160" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.33", ] [[package]] @@ -1670,6 +1921,16 @@ dependencies = [ "syn 1.0.107", ] +[[package]] +name = "smtp-notifier" +version = "0.6.0" +dependencies = [ + "lettre", + "openssl", + "pulsar-core", + "tokio", +] + [[package]] name = "socket2" version = "0.4.7" @@ -1737,9 +1998,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.15" +version = "2.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "9caece70c63bfba29ec2fed841a09851b14a235c60010fa4de58089b6c025668" dependencies = [ "proc-macro2", "quote", @@ -1765,6 +2026,19 @@ dependencies = [ "tracing", ] +[[package]] +name = "tempfile" +version = "3.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +dependencies = [ + "cfg-if", + "fastrand", + "redox_syscall 0.3.5", + "rustix 0.37.3", + "windows-sys 0.45.0", +] + [[package]] name = "term" version = "0.7.0" @@ -1818,7 +2092,7 @@ checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.33", ] [[package]] @@ -1895,6 +2169,16 @@ dependencies = [ "syn 1.0.107", ] +[[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-tungstenite" version = "0.18.0" @@ -2042,9 +2326,9 @@ checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "unicode-bidi" -version = "0.3.9" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046be40136ef78dc325e0edefccf84ccddacd0afcc1ca54103fa3c61bbdab1d" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" @@ -2087,12 +2371,12 @@ checksum = "1865806a559042e51ab5414598446a5871b561d21b6764f2eabb0dd481d880a6" [[package]] name = "url" -version = "2.3.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ "form_urlencoded", - "idna", + "idna 0.4.0", "percent-encoding", ] @@ -2124,9 +2408,15 @@ version = "0.6.0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.15", + "syn 2.0.33", ] +[[package]] +name = "vcpkg" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index 4bc8c764..7740d7b0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ network-monitor = { path = "crates/modules/network-monitor", optional = true } logger = { path = "crates/modules/logger", optional = true } rules-engine = { path = "crates/modules/rules-engine", optional = true } desktop-notifier = { path = "crates/modules/desktop-notifier", optional = true } +smtp-notifier = { path = "crates/modules/smtp-notifier", optional = true } # External tokio = { version = "1.15.0", features = ["full"] } env_logger = "0.10.0" @@ -41,7 +42,8 @@ futures-util = "0.3.25" [features] default = ["core", "extra"] core = ["logger", "process-monitor", "network-monitor", "file-system-monitor"] -extra = ["rules-engine", "desktop-notifier"] +extra = ["rules-engine", "desktop-notifier", "smtp-notifier"] +openssl-vendored = ["smtp-notifier?/openssl-vendored"] [workspace] members = [ @@ -51,6 +53,7 @@ members = [ "crates/modules/rules-engine", "crates/modules/logger", "crates/modules/desktop-notifier", + "crates/modules/smtp-notifier", "crates/pulsar-core", "crates/bpf-common", "crates/bpf-builder", diff --git a/crates/modules/smtp-notifier/Cargo.toml b/crates/modules/smtp-notifier/Cargo.toml new file mode 100644 index 00000000..54be1175 --- /dev/null +++ b/crates/modules/smtp-notifier/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "smtp-notifier" +version.workspace = true +license.workspace = true +edition.workspace = true +repository.workspace = true + +[dependencies] +pulsar-core = { path = "../../pulsar-core" } + +tokio = { version = "1", features = ["full"] } +openssl = { version = "0.10.57", optional = true } +lettre = { version = "0.10.4", default-features = false, features = ["smtp-transport", "tokio1-native-tls", "tokio1", "builder"] } + +[features] +openssl-vendored = ["openssl/vendored"] diff --git a/crates/modules/smtp-notifier/README.md b/crates/modules/smtp-notifier/README.md new file mode 100644 index 00000000..5ee5b919 --- /dev/null +++ b/crates/modules/smtp-notifier/README.md @@ -0,0 +1,33 @@ +# Smtp notifier + +This module will send an email notification when Pulsar identifies a threat. + +## Configuration + +|Config|Type|Description| +|------|----|-----------| +|`user`|string|user credential for smtp server| +|`password`|string|password credential for smtp server| +|`server`|string|smtp server url to use| +|`receiver`|string|email to send notifications to| +|`port`|int|port for smtp server| +|`encryption`|string|encryption type to use for smtp: tls, start-tls, plain| +|`set_from`|bool|set the from header to Pulsar | + +```ini +[smtp-notifier] +enabled=true +user=youremail@gmail.com +password= +server=smtp.gmail.com +receiver=receiver@gmail.com +port=465 +encryption=tls +set_from=true +``` + +You can disable this module with: + +```sh +pulsar config --set smtp-notifier.enabled=false +``` diff --git a/crates/modules/smtp-notifier/src/lib.rs b/crates/modules/smtp-notifier/src/lib.rs new file mode 100644 index 00000000..e9942064 --- /dev/null +++ b/crates/modules/smtp-notifier/src/lib.rs @@ -0,0 +1,149 @@ +use std::{default::Default, error::Error, fmt, str::FromStr}; + +use pulsar_core::event::Threat; +use pulsar_core::pdk::{ + CleanExit, ConfigError, ModuleConfig, ModuleContext, ModuleError, PulsarModule, ShutdownSignal, + Version, +}; + +use lettre::{ + transport::smtp::authentication::Credentials, AsyncSmtpTransport, AsyncTransport, Message, + Tokio1Executor, +}; + +const MODULE_NAME: &str = "smtp-notifier"; + +pub fn module() -> PulsarModule { + PulsarModule::new( + MODULE_NAME, + Version::parse(env!("CARGO_PKG_VERSION")).unwrap(), + smtp_notifier_task, + ) +} + +async fn smtp_notifier_task( + ctx: ModuleContext, + mut shutdown: ShutdownSignal, +) -> Result { + let mut receiver = ctx.get_receiver(); + let mut rx_config = ctx.get_config(); + let mut config: SmtpNotifierConfig = rx_config.read()?; + + loop { + tokio::select! { + // Handle configuration changes: + _ = rx_config.changed() => { + config = rx_config.read()?; + continue; + } + r = shutdown.recv() => return r, + msg = receiver.recv() => { + let event = msg?; + + // Check if the even is a threat and send a email if it is + if let Some(Threat { + source, + description, + extra: _, + }) = &event.header().threat + { + let payload = event.payload(); + let subject = format!("Pulsar Threat Notification: {source}"); + let body = format!("{description}\n Source event: {payload}"); + + let mut message_builder = Message::builder() + .to(config.receiver.parse()?) + .subject(subject); + + if config.set_from { + message_builder = message_builder.from("Pulsar ".parse()?); + } + + let message = message_builder.body(body)?; + + let smtp_transport = match config.encryption { + Encryption::Plain => { + AsyncSmtpTransport::::builder_dangerous(config.server.as_str()) + } + Encryption::Tls => AsyncSmtpTransport::::relay(config.server.as_str())?, + Encryption::StartTls => { + AsyncSmtpTransport::::starttls_relay(config.server.as_str())? + } + }; + + smtp_transport + .credentials(Credentials::new(config.user.clone(), config.password.clone())) + .port(config.port) + .build() + .send(message) + .await?; + } + } + } + } +} + +#[derive(Debug)] +struct ParseEncryptionError; + +impl Error for ParseEncryptionError {} + +impl fmt::Display for ParseEncryptionError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self) + } +} + +#[derive(Debug, Default, Clone, Copy)] +enum Encryption { + #[default] + Tls, + StartTls, + Plain, +} + +impl fmt::Display for Encryption { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self) + } +} + +impl FromStr for Encryption { + type Err = ParseEncryptionError; + + fn from_str(s: &str) -> Result { + match s { + "plain" => Ok(Encryption::Plain), + "tls" => Ok(Encryption::Tls), + "start-tls" => Ok(Encryption::StartTls), + _ => Err(ParseEncryptionError), + } + } +} + +#[derive(Clone, Debug, Default)] +struct SmtpNotifierConfig { + server: String, + user: String, + password: String, + receiver: String, + port: u16, + encryption: Encryption, + set_from: bool, +} + +impl TryFrom<&ModuleConfig> for SmtpNotifierConfig { + type Error = ConfigError; + + fn try_from(config: &ModuleConfig) -> Result { + Ok(SmtpNotifierConfig { + server: config.required::("server")?, + user: config.required::("user")?, + password: config.required::("password")?, + receiver: config.required::("receiver")?, + port: config.with_default::("port", 465)?, + encryption: config.with_default::("encryption", Default::default())?, + set_from: config.with_default::("set_from", true)?, + }) + } +} diff --git a/crates/validatron/src/reflection/adt.rs b/crates/validatron/src/reflection/adt.rs index 7e37c80e..14a6b6d6 100644 --- a/crates/validatron/src/reflection/adt.rs +++ b/crates/validatron/src/reflection/adt.rs @@ -81,7 +81,7 @@ fn add_variant( ) { if fields_map .entry(variant_name) - .or_insert(HashMap::new()) + .or_default() .insert(field_name, variant) .is_some() { diff --git a/pulsar-install.sh b/pulsar-install.sh index 347a252f..0adb975b 100644 --- a/pulsar-install.sh +++ b/pulsar-install.sh @@ -316,4 +316,4 @@ ignore() { "$@" } -main "$@" || exit 1 \ No newline at end of file +main "$@" || exit 1 diff --git a/src/lib.rs b/src/lib.rs index b03863de..5fc6efa0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,6 +94,8 @@ pub fn modules() -> Vec> { rules_engine::module(), #[cfg(feature = "desktop-notifier")] desktop_notifier::module(), + #[cfg(feature = "smtp-notifier")] + smtp_notifier::module(), ] .into_iter() .map(|x| Box::new(x) as Box)