├── .github └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── Makefile ├── OWNERS ├── README.md ├── examples └── outputs.rs └── src ├── api ├── mod.rs ├── output.rs ├── output_grpc.rs └── schema.rs ├── certs.rs ├── client.rs ├── config.rs ├── errors.rs ├── lib.rs └── macros.rs /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 11 | 12 | **What type of PR is this?** 13 | 14 | > Uncomment one (or more) `/kind <>` lines: 15 | 16 | > /kind bug 17 | 18 | > /kind cleanup 19 | 20 | > /kind documentation 21 | 22 | > /kind failing-test 23 | 24 | > /kind feature 25 | 26 | **Any specific area of the project related to this PR?** 27 | 28 | > Uncomment one (or more) `/area <>` lines: 29 | 30 | > /area api 31 | 32 | > /area client 33 | 34 | > /area tests 35 | 36 | > /area examples 37 | 38 | > /area build 39 | 40 | **What this PR does / why we need it**: 41 | 42 | **Which issue(s) this PR fixes**: 43 | 44 | 49 | 50 | Fixes # 51 | 52 | **Special notes for your reviewer**: 53 | 54 | **Does this PR introduce a user-facing change?**: 55 | 56 | 63 | 64 | ```release-note 65 | 66 | ``` 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | /protos -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | [[package]] 4 | name = "backtrace" 5 | version = "0.3.40" 6 | source = "registry+https://github.com/rust-lang/crates.io-index" 7 | dependencies = [ 8 | "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", 9 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 10 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 11 | "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", 12 | ] 13 | 14 | [[package]] 15 | name = "backtrace-sys" 16 | version = "0.1.32" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | dependencies = [ 19 | "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", 20 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 21 | ] 22 | 23 | [[package]] 24 | name = "cc" 25 | version = "1.0.49" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | 28 | [[package]] 29 | name = "cfg-if" 30 | version = "0.1.10" 31 | source = "registry+https://github.com/rust-lang/crates.io-index" 32 | 33 | [[package]] 34 | name = "cmake" 35 | version = "0.1.42" 36 | source = "registry+https://github.com/rust-lang/crates.io-index" 37 | dependencies = [ 38 | "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", 39 | ] 40 | 41 | [[package]] 42 | name = "failure" 43 | version = "0.1.6" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | dependencies = [ 46 | "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", 47 | "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 48 | ] 49 | 50 | [[package]] 51 | name = "failure_derive" 52 | version = "0.1.6" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | dependencies = [ 55 | "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", 56 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 57 | "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", 58 | "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", 59 | ] 60 | 61 | [[package]] 62 | name = "falco" 63 | version = "0.0.0" 64 | dependencies = [ 65 | "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", 66 | "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", 67 | "grpcio 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", 68 | "grpcio-compiler 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", 69 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 70 | "protobuf 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 71 | "protobuf-codegen 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 72 | "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", 73 | "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", 74 | ] 75 | 76 | [[package]] 77 | name = "futures" 78 | version = "0.1.29" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | 81 | [[package]] 82 | name = "grpcio" 83 | version = "0.4.7" 84 | source = "registry+https://github.com/rust-lang/crates.io-index" 85 | dependencies = [ 86 | "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", 87 | "grpcio-sys 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", 88 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 89 | "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", 90 | "protobuf 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 91 | ] 92 | 93 | [[package]] 94 | name = "grpcio-compiler" 95 | version = "0.4.3" 96 | source = "registry+https://github.com/rust-lang/crates.io-index" 97 | dependencies = [ 98 | "protobuf 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 99 | "protobuf-codegen 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 100 | ] 101 | 102 | [[package]] 103 | name = "grpcio-sys" 104 | version = "0.4.7" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | dependencies = [ 107 | "cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)", 108 | "cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", 109 | "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", 110 | "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", 111 | ] 112 | 113 | [[package]] 114 | name = "libc" 115 | version = "0.2.66" 116 | source = "registry+https://github.com/rust-lang/crates.io-index" 117 | 118 | [[package]] 119 | name = "log" 120 | version = "0.4.8" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | dependencies = [ 123 | "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", 124 | ] 125 | 126 | [[package]] 127 | name = "pkg-config" 128 | version = "0.3.17" 129 | source = "registry+https://github.com/rust-lang/crates.io-index" 130 | 131 | [[package]] 132 | name = "proc-macro2" 133 | version = "1.0.7" 134 | source = "registry+https://github.com/rust-lang/crates.io-index" 135 | dependencies = [ 136 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 137 | ] 138 | 139 | [[package]] 140 | name = "protobuf" 141 | version = "2.10.0" 142 | source = "registry+https://github.com/rust-lang/crates.io-index" 143 | 144 | [[package]] 145 | name = "protobuf-codegen" 146 | version = "2.10.0" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | dependencies = [ 149 | "protobuf 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)", 150 | ] 151 | 152 | [[package]] 153 | name = "quote" 154 | version = "1.0.2" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | dependencies = [ 157 | "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", 158 | ] 159 | 160 | [[package]] 161 | name = "rustc-demangle" 162 | version = "0.1.16" 163 | source = "registry+https://github.com/rust-lang/crates.io-index" 164 | 165 | [[package]] 166 | name = "serde" 167 | version = "1.0.104" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | 170 | [[package]] 171 | name = "serde_derive" 172 | version = "1.0.104" 173 | source = "registry+https://github.com/rust-lang/crates.io-index" 174 | dependencies = [ 175 | "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", 176 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 177 | "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", 178 | ] 179 | 180 | [[package]] 181 | name = "syn" 182 | version = "1.0.13" 183 | source = "registry+https://github.com/rust-lang/crates.io-index" 184 | dependencies = [ 185 | "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", 186 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 187 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 188 | ] 189 | 190 | [[package]] 191 | name = "synstructure" 192 | version = "0.12.3" 193 | source = "registry+https://github.com/rust-lang/crates.io-index" 194 | dependencies = [ 195 | "proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", 196 | "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", 197 | "syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", 198 | "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", 199 | ] 200 | 201 | [[package]] 202 | name = "unicode-xid" 203 | version = "0.2.0" 204 | source = "registry+https://github.com/rust-lang/crates.io-index" 205 | 206 | [metadata] 207 | "checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" 208 | "checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" 209 | "checksum cc 1.0.49 (registry+https://github.com/rust-lang/crates.io-index)" = "e450b8da92aa6f274e7c6437692f9f2ce6d701fb73bacfcf87897b3f89a4c20e" 210 | "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" 211 | "checksum cmake 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "81fb25b677f8bf1eb325017cb6bb8452f87969db0fedb4f757b297bee78a7c62" 212 | "checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" 213 | "checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" 214 | "checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" 215 | "checksum grpcio 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9ac757a85603e4f8c40a9f94be06a5ad412acab80b39b4e8895ca931b6619910" 216 | "checksum grpcio-compiler 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "373a14f0f994d4c235770f4bb5558be00626844db130a82a70142b8fc5996fc3" 217 | "checksum grpcio-sys 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "7b2f22fb0327f153acccedbe91894dd0fb15bb6f202d8195665cd206af0402b0" 218 | "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" 219 | "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" 220 | "checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" 221 | "checksum proc-macro2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0319972dcae462681daf4da1adeeaa066e3ebd29c69be96c6abb1259d2ee2bcc" 222 | "checksum protobuf 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6563a657a014b771e7f69f06447d88d8fbb5a215ffc4cab724afb3acedcc7701" 223 | "checksum protobuf-codegen 2.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6f1bbc6db30d5d3e730b6e2326e9a64a75ca9c80d6427d6f054dc8cacc79d225" 224 | "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" 225 | "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" 226 | "checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" 227 | "checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" 228 | "checksum syn 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1e4ff033220a41d1a57d8125eab57bf5263783dfdcc18688b1dacc6ce9651ef8" 229 | "checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" 230 | "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" 231 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "falco" 3 | version = "0.0.0" 4 | authors = ["Lorenzo Fontana ", "Leonardo Di Donato "] 5 | edition = "2018" 6 | publish = true 7 | homepage = "https://github.com/falcosecurity/client-rs" 8 | documentation = "https://docs.rs/falco" 9 | description = "The rust language implementation of the Falco client." 10 | license = "Apache-2.0" 11 | keywords = ["falco", "falcosecurity", "kubernetes", "security"] 12 | 13 | [dependencies] 14 | grpcio = { version = "0.4.7", features = ["openssl"] } 15 | failure = "0.1" 16 | futures = "^0.1.15" 17 | protobuf = "~2" 18 | log = "0.4" 19 | serde = "1.0" 20 | serde_derive = "1.0" 21 | 22 | [dev-dependencies] 23 | protobuf-codegen = "~2" 24 | grpcio-compiler = "*" -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | Copyright 2019 The Falco Authors 180 | 181 | Licensed under the Apache License, Version 2.0 (the "License"); 182 | you may not use this file except in compliance with the License. 183 | You may obtain a copy of the License at 184 | 185 | http://www.apache.org/licenses/LICENSE-2.0 186 | 187 | Unless required by applicable law or agreed to in writing, software 188 | distributed under the License is distributed on an "AS IS" BASIS, 189 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 190 | See the License for the specific language governing permissions and 191 | limitations under the License. -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SHELL := /bin/bash 2 | 3 | PROTOC ?= $(shell which protoc) 4 | GRPC_RUST_PLUGIN ?= $(shell which grpc_rust_plugin) 5 | 6 | PROTOS := protos/schema.proto protos/output.proto 7 | PROTO_URLS := https://raw.githubusercontent.com/falcosecurity/falco/master/userspace/falco/schema.proto https://raw.githubusercontent.com/falcosecurity/falco/master/userspace/falco/output.proto 8 | PROTO_SHAS := a1f427c114b945d0880b55058862b74015d036aa722985ca6e5474ab4ed19f69 4ce2f3e6d6ebc07a74535c4f21da73e44c6ef848ab83627b1ac987058be5ece9 9 | 10 | PROTO_DIRS := $(dir ${PROTOS}) 11 | PROTO_DIRS_INCLUDES := $(patsubst %/, -I %, ${PROTO_DIRS}) 12 | 13 | .PHONY: protos 14 | protos: ${PROTOS} 15 | 16 | # $(1): the proto path 17 | # $(2): the proto URL 18 | # $(3): the proto SHA256 19 | define download_rule 20 | $(1): 21 | @rm -f $(1) 22 | @mkdir -p ${PROTO_DIRS} 23 | @curl --silent -Lo $(1) $(2) 24 | @echo $(3) $(1) | sha256sum -c 25 | @sed -i '/option go_package/d' $(1) 26 | @${PROTOC} ${PROTO_DIRS_INCLUDES} --rust_out=src/api --grpc_out=src/api --plugin=protoc-gen-grpc=${GRPC_RUST_PLUGIN} $(1) 27 | endef 28 | $(foreach PROTO,$(PROTOS),\ 29 | $(eval $(call download_rule,$(PROTO),$(firstword $(PROTO_URLS)),$(firstword $(PROTO_SHAS))))\ 30 | $(eval PROTO_URLS := $(wordlist 2,$(words $(PROTO_URLS)),$(PROTO_URLS)))\ 31 | $(eval PROTO_SHAS := $(wordlist 2,$(words $(PROTO_SHAS)),$(PROTO_SHAS)))\ 32 | ) 33 | 34 | .PHONY: clean 35 | clean: ${PROTO_DIRS} 36 | @rm -rf $^ 37 | -------------------------------------------------------------------------------- /OWNERS: -------------------------------------------------------------------------------- 1 | approvers: 2 | - leodido 3 | - fntlnz 4 | reviewers: 5 | - leodido 6 | - fntlnz 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Falco Rust Client 2 | 3 | [![crates](https://img.shields.io/badge/crates.io-v0.0.0-orange.svg?style=flat-square&longCache=true)](https://crates.io/crates/falco) 4 | 5 | > The rust language implementation of the Falco client 6 | 7 | ## Install 8 | 9 | To include as a dependency: 10 | 11 | ```toml 12 | [dependencies] 13 | falco = "0.0.0" 14 | ``` 15 | 16 | ## Full Examples 17 | 18 | - [Output events example](examples/outputs.rs) 19 | 20 | To execute any example: 21 | 22 | ```console 23 | cargo run --example 24 | ``` 25 | 26 | Where `` needs to be changed with the file name of the example. 27 | 28 | ## Update protos 29 | 30 | Do you want/need to update the proto files? 31 | 32 | We provided a make command - ie., `make protos` - to update them. 33 | 34 | ```console 35 | make clean 36 | make 37 | ``` 38 | -------------------------------------------------------------------------------- /examples/outputs.rs: -------------------------------------------------------------------------------- 1 | use falco::api::output; 2 | use falco::client::Client; 3 | use falco::config::Config; 4 | use futures::{Future, Stream}; 5 | 6 | fn main() { 7 | // gRPC configuration 8 | // with_auth is mandatory, Falco only supports mutual TLS connections. 9 | let config = Config::new("localhost:5060").with_auth( 10 | "/tmp/certs/ca.crt", 11 | "/tmp/certs/client.crt", 12 | "/tmp/certs/client.key", 13 | ); 14 | 15 | // gRPC client 16 | let client = Client::new(config).unwrap(); 17 | 18 | // Output request 19 | // Keepalive true means that the client will wait indefinitely for new events to come 20 | // Use keepalive false if you only want to receive the accumulated events and stop 21 | let mut req = output::request::default(); 22 | req.keepalive = true; 23 | 24 | // Subscribe to output events 25 | let mut res = client.outputs().subscribe(&req).unwrap(); 26 | 27 | // Consume the events 28 | loop { 29 | let f = res.into_future(); 30 | match f.wait() { 31 | Ok((Some(element), s)) => { 32 | res = s; 33 | println!("{:#?}", element); 34 | } 35 | // EOF 36 | Ok((None, _)) => break, 37 | // Error 38 | Err((e, _)) => panic!("error: {:?}", e), 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/api/mod.rs: -------------------------------------------------------------------------------- 1 | extern crate futures; 2 | extern crate grpcio; 3 | extern crate protobuf; 4 | 5 | pub mod output; 6 | pub mod output_grpc; 7 | 8 | pub mod schema; 9 | -------------------------------------------------------------------------------- /src/api/output.rs: -------------------------------------------------------------------------------- 1 | // This file is generated by rust-protobuf 2.10.1. Do not edit 2 | // @generated 3 | 4 | // https://github.com/rust-lang/rust-clippy/issues/702 5 | #![allow(unknown_lints)] 6 | #![allow(clippy::all)] 7 | 8 | #![cfg_attr(rustfmt, rustfmt_skip)] 9 | 10 | #![allow(box_pointers)] 11 | #![allow(dead_code)] 12 | #![allow(missing_docs)] 13 | #![allow(non_camel_case_types)] 14 | #![allow(non_snake_case)] 15 | #![allow(non_upper_case_globals)] 16 | #![allow(trivial_casts)] 17 | #![allow(unsafe_code)] 18 | #![allow(unused_imports)] 19 | #![allow(unused_results)] 20 | //! Generated file from `output.proto` 21 | 22 | use protobuf::Message as Message_imported_for_functions; 23 | use protobuf::ProtobufEnum as ProtobufEnum_imported_for_functions; 24 | 25 | /// Generated files are compatible only with the same version 26 | /// of protobuf runtime. 27 | // const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_10_1; 28 | 29 | #[derive(PartialEq,Clone,Default)] 30 | pub struct request { 31 | // message fields 32 | pub keepalive: bool, 33 | // special fields 34 | pub unknown_fields: ::protobuf::UnknownFields, 35 | pub cached_size: ::protobuf::CachedSize, 36 | } 37 | 38 | impl<'a> ::std::default::Default for &'a request { 39 | fn default() -> &'a request { 40 | ::default_instance() 41 | } 42 | } 43 | 44 | impl request { 45 | pub fn new() -> request { 46 | ::std::default::Default::default() 47 | } 48 | 49 | // bool keepalive = 1; 50 | 51 | 52 | pub fn get_keepalive(&self) -> bool { 53 | self.keepalive 54 | } 55 | pub fn clear_keepalive(&mut self) { 56 | self.keepalive = false; 57 | } 58 | 59 | // Param is passed by value, moved 60 | pub fn set_keepalive(&mut self, v: bool) { 61 | self.keepalive = v; 62 | } 63 | } 64 | 65 | impl ::protobuf::Message for request { 66 | fn is_initialized(&self) -> bool { 67 | true 68 | } 69 | 70 | fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { 71 | while !is.eof()? { 72 | let (field_number, wire_type) = is.read_tag_unpack()?; 73 | match field_number { 74 | 1 => { 75 | if wire_type != ::protobuf::wire_format::WireTypeVarint { 76 | return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type)); 77 | } 78 | let tmp = is.read_bool()?; 79 | self.keepalive = tmp; 80 | }, 81 | _ => { 82 | ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; 83 | }, 84 | }; 85 | } 86 | ::std::result::Result::Ok(()) 87 | } 88 | 89 | // Compute sizes of nested messages 90 | #[allow(unused_variables)] 91 | fn compute_size(&self) -> u32 { 92 | let mut my_size = 0; 93 | if self.keepalive != false { 94 | my_size += 2; 95 | } 96 | my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); 97 | self.cached_size.set(my_size); 98 | my_size 99 | } 100 | 101 | fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { 102 | if self.keepalive != false { 103 | os.write_bool(1, self.keepalive)?; 104 | } 105 | os.write_unknown_fields(self.get_unknown_fields())?; 106 | ::std::result::Result::Ok(()) 107 | } 108 | 109 | fn get_cached_size(&self) -> u32 { 110 | self.cached_size.get() 111 | } 112 | 113 | fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { 114 | &self.unknown_fields 115 | } 116 | 117 | fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { 118 | &mut self.unknown_fields 119 | } 120 | 121 | fn as_any(&self) -> &dyn (::std::any::Any) { 122 | self as &dyn (::std::any::Any) 123 | } 124 | fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { 125 | self as &mut dyn (::std::any::Any) 126 | } 127 | fn into_any(self: Box) -> ::std::boxed::Box { 128 | self 129 | } 130 | 131 | fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { 132 | Self::descriptor_static() 133 | } 134 | 135 | fn new() -> request { 136 | request::new() 137 | } 138 | 139 | fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { 140 | static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { 141 | lock: ::protobuf::lazy::ONCE_INIT, 142 | ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, 143 | }; 144 | unsafe { 145 | descriptor.get(|| { 146 | let mut fields = ::std::vec::Vec::new(); 147 | fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBool>( 148 | "keepalive", 149 | |m: &request| { &m.keepalive }, 150 | |m: &mut request| { &mut m.keepalive }, 151 | )); 152 | ::protobuf::reflect::MessageDescriptor::new::( 153 | "request", 154 | fields, 155 | file_descriptor_proto() 156 | ) 157 | }) 158 | } 159 | } 160 | 161 | fn default_instance() -> &'static request { 162 | static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { 163 | lock: ::protobuf::lazy::ONCE_INIT, 164 | ptr: 0 as *const request, 165 | }; 166 | unsafe { 167 | instance.get(request::new) 168 | } 169 | } 170 | } 171 | 172 | impl ::protobuf::Clear for request { 173 | fn clear(&mut self) { 174 | self.keepalive = false; 175 | self.unknown_fields.clear(); 176 | } 177 | } 178 | 179 | impl ::std::fmt::Debug for request { 180 | fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 181 | ::protobuf::text_format::fmt(self, f) 182 | } 183 | } 184 | 185 | impl ::protobuf::reflect::ProtobufValue for request { 186 | fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { 187 | ::protobuf::reflect::ProtobufValueRef::Message(self) 188 | } 189 | } 190 | 191 | #[derive(PartialEq,Clone,Default)] 192 | pub struct response { 193 | // message fields 194 | pub time: ::protobuf::SingularPtrField<::protobuf::well_known_types::Timestamp>, 195 | pub priority: super::schema::priority, 196 | pub source: super::schema::source, 197 | pub rule: ::std::string::String, 198 | pub output: ::std::string::String, 199 | pub output_fields: ::std::collections::HashMap<::std::string::String, ::std::string::String>, 200 | pub hostname: ::std::string::String, 201 | // special fields 202 | pub unknown_fields: ::protobuf::UnknownFields, 203 | pub cached_size: ::protobuf::CachedSize, 204 | } 205 | 206 | impl<'a> ::std::default::Default for &'a response { 207 | fn default() -> &'a response { 208 | ::default_instance() 209 | } 210 | } 211 | 212 | impl response { 213 | pub fn new() -> response { 214 | ::std::default::Default::default() 215 | } 216 | 217 | // .google.protobuf.Timestamp time = 1; 218 | 219 | 220 | pub fn get_time(&self) -> &::protobuf::well_known_types::Timestamp { 221 | self.time.as_ref().unwrap_or_else(|| ::protobuf::well_known_types::Timestamp::default_instance()) 222 | } 223 | pub fn clear_time(&mut self) { 224 | self.time.clear(); 225 | } 226 | 227 | pub fn has_time(&self) -> bool { 228 | self.time.is_some() 229 | } 230 | 231 | // Param is passed by value, moved 232 | pub fn set_time(&mut self, v: ::protobuf::well_known_types::Timestamp) { 233 | self.time = ::protobuf::SingularPtrField::some(v); 234 | } 235 | 236 | // Mutable pointer to the field. 237 | // If field is not initialized, it is initialized with default value first. 238 | pub fn mut_time(&mut self) -> &mut ::protobuf::well_known_types::Timestamp { 239 | if self.time.is_none() { 240 | self.time.set_default(); 241 | } 242 | self.time.as_mut().unwrap() 243 | } 244 | 245 | // Take field 246 | pub fn take_time(&mut self) -> ::protobuf::well_known_types::Timestamp { 247 | self.time.take().unwrap_or_else(|| ::protobuf::well_known_types::Timestamp::new()) 248 | } 249 | 250 | // .falco.schema.priority priority = 2; 251 | 252 | 253 | pub fn get_priority(&self) -> super::schema::priority { 254 | self.priority 255 | } 256 | pub fn clear_priority(&mut self) { 257 | self.priority = super::schema::priority::EMERGENCY; 258 | } 259 | 260 | // Param is passed by value, moved 261 | pub fn set_priority(&mut self, v: super::schema::priority) { 262 | self.priority = v; 263 | } 264 | 265 | // .falco.schema.source source = 3; 266 | 267 | 268 | pub fn get_source(&self) -> super::schema::source { 269 | self.source 270 | } 271 | pub fn clear_source(&mut self) { 272 | self.source = super::schema::source::SYSCALL; 273 | } 274 | 275 | // Param is passed by value, moved 276 | pub fn set_source(&mut self, v: super::schema::source) { 277 | self.source = v; 278 | } 279 | 280 | // string rule = 4; 281 | 282 | 283 | pub fn get_rule(&self) -> &str { 284 | &self.rule 285 | } 286 | pub fn clear_rule(&mut self) { 287 | self.rule.clear(); 288 | } 289 | 290 | // Param is passed by value, moved 291 | pub fn set_rule(&mut self, v: ::std::string::String) { 292 | self.rule = v; 293 | } 294 | 295 | // Mutable pointer to the field. 296 | // If field is not initialized, it is initialized with default value first. 297 | pub fn mut_rule(&mut self) -> &mut ::std::string::String { 298 | &mut self.rule 299 | } 300 | 301 | // Take field 302 | pub fn take_rule(&mut self) -> ::std::string::String { 303 | ::std::mem::replace(&mut self.rule, ::std::string::String::new()) 304 | } 305 | 306 | // string output = 5; 307 | 308 | 309 | pub fn get_output(&self) -> &str { 310 | &self.output 311 | } 312 | pub fn clear_output(&mut self) { 313 | self.output.clear(); 314 | } 315 | 316 | // Param is passed by value, moved 317 | pub fn set_output(&mut self, v: ::std::string::String) { 318 | self.output = v; 319 | } 320 | 321 | // Mutable pointer to the field. 322 | // If field is not initialized, it is initialized with default value first. 323 | pub fn mut_output(&mut self) -> &mut ::std::string::String { 324 | &mut self.output 325 | } 326 | 327 | // Take field 328 | pub fn take_output(&mut self) -> ::std::string::String { 329 | ::std::mem::replace(&mut self.output, ::std::string::String::new()) 330 | } 331 | 332 | // repeated .falco.output.response.OutputFieldsEntry output_fields = 6; 333 | 334 | 335 | pub fn get_output_fields(&self) -> &::std::collections::HashMap<::std::string::String, ::std::string::String> { 336 | &self.output_fields 337 | } 338 | pub fn clear_output_fields(&mut self) { 339 | self.output_fields.clear(); 340 | } 341 | 342 | // Param is passed by value, moved 343 | pub fn set_output_fields(&mut self, v: ::std::collections::HashMap<::std::string::String, ::std::string::String>) { 344 | self.output_fields = v; 345 | } 346 | 347 | // Mutable pointer to the field. 348 | pub fn mut_output_fields(&mut self) -> &mut ::std::collections::HashMap<::std::string::String, ::std::string::String> { 349 | &mut self.output_fields 350 | } 351 | 352 | // Take field 353 | pub fn take_output_fields(&mut self) -> ::std::collections::HashMap<::std::string::String, ::std::string::String> { 354 | ::std::mem::replace(&mut self.output_fields, ::std::collections::HashMap::new()) 355 | } 356 | 357 | // string hostname = 7; 358 | 359 | 360 | pub fn get_hostname(&self) -> &str { 361 | &self.hostname 362 | } 363 | pub fn clear_hostname(&mut self) { 364 | self.hostname.clear(); 365 | } 366 | 367 | // Param is passed by value, moved 368 | pub fn set_hostname(&mut self, v: ::std::string::String) { 369 | self.hostname = v; 370 | } 371 | 372 | // Mutable pointer to the field. 373 | // If field is not initialized, it is initialized with default value first. 374 | pub fn mut_hostname(&mut self) -> &mut ::std::string::String { 375 | &mut self.hostname 376 | } 377 | 378 | // Take field 379 | pub fn take_hostname(&mut self) -> ::std::string::String { 380 | ::std::mem::replace(&mut self.hostname, ::std::string::String::new()) 381 | } 382 | } 383 | 384 | impl ::protobuf::Message for response { 385 | fn is_initialized(&self) -> bool { 386 | for v in &self.time { 387 | if !v.is_initialized() { 388 | return false; 389 | } 390 | }; 391 | true 392 | } 393 | 394 | fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> { 395 | while !is.eof()? { 396 | let (field_number, wire_type) = is.read_tag_unpack()?; 397 | match field_number { 398 | 1 => { 399 | ::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.time)?; 400 | }, 401 | 2 => { 402 | ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.priority, 2, &mut self.unknown_fields)? 403 | }, 404 | 3 => { 405 | ::protobuf::rt::read_proto3_enum_with_unknown_fields_into(wire_type, is, &mut self.source, 3, &mut self.unknown_fields)? 406 | }, 407 | 4 => { 408 | ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.rule)?; 409 | }, 410 | 5 => { 411 | ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.output)?; 412 | }, 413 | 6 => { 414 | ::protobuf::rt::read_map_into::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeString>(wire_type, is, &mut self.output_fields)?; 415 | }, 416 | 7 => { 417 | ::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.hostname)?; 418 | }, 419 | _ => { 420 | ::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?; 421 | }, 422 | }; 423 | } 424 | ::std::result::Result::Ok(()) 425 | } 426 | 427 | // Compute sizes of nested messages 428 | #[allow(unused_variables)] 429 | fn compute_size(&self) -> u32 { 430 | let mut my_size = 0; 431 | if let Some(ref v) = self.time.as_ref() { 432 | let len = v.compute_size(); 433 | my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len; 434 | } 435 | if self.priority != super::schema::priority::EMERGENCY { 436 | my_size += ::protobuf::rt::enum_size(2, self.priority); 437 | } 438 | if self.source != super::schema::source::SYSCALL { 439 | my_size += ::protobuf::rt::enum_size(3, self.source); 440 | } 441 | if !self.rule.is_empty() { 442 | my_size += ::protobuf::rt::string_size(4, &self.rule); 443 | } 444 | if !self.output.is_empty() { 445 | my_size += ::protobuf::rt::string_size(5, &self.output); 446 | } 447 | my_size += ::protobuf::rt::compute_map_size::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeString>(6, &self.output_fields); 448 | if !self.hostname.is_empty() { 449 | my_size += ::protobuf::rt::string_size(7, &self.hostname); 450 | } 451 | my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields()); 452 | self.cached_size.set(my_size); 453 | my_size 454 | } 455 | 456 | fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> { 457 | if let Some(ref v) = self.time.as_ref() { 458 | os.write_tag(1, ::protobuf::wire_format::WireTypeLengthDelimited)?; 459 | os.write_raw_varint32(v.get_cached_size())?; 460 | v.write_to_with_cached_sizes(os)?; 461 | } 462 | if self.priority != super::schema::priority::EMERGENCY { 463 | os.write_enum(2, self.priority.value())?; 464 | } 465 | if self.source != super::schema::source::SYSCALL { 466 | os.write_enum(3, self.source.value())?; 467 | } 468 | if !self.rule.is_empty() { 469 | os.write_string(4, &self.rule)?; 470 | } 471 | if !self.output.is_empty() { 472 | os.write_string(5, &self.output)?; 473 | } 474 | ::protobuf::rt::write_map_with_cached_sizes::<::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeString>(6, &self.output_fields, os)?; 475 | if !self.hostname.is_empty() { 476 | os.write_string(7, &self.hostname)?; 477 | } 478 | os.write_unknown_fields(self.get_unknown_fields())?; 479 | ::std::result::Result::Ok(()) 480 | } 481 | 482 | fn get_cached_size(&self) -> u32 { 483 | self.cached_size.get() 484 | } 485 | 486 | fn get_unknown_fields(&self) -> &::protobuf::UnknownFields { 487 | &self.unknown_fields 488 | } 489 | 490 | fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields { 491 | &mut self.unknown_fields 492 | } 493 | 494 | fn as_any(&self) -> &dyn (::std::any::Any) { 495 | self as &dyn (::std::any::Any) 496 | } 497 | fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) { 498 | self as &mut dyn (::std::any::Any) 499 | } 500 | fn into_any(self: Box) -> ::std::boxed::Box { 501 | self 502 | } 503 | 504 | fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor { 505 | Self::descriptor_static() 506 | } 507 | 508 | fn new() -> response { 509 | response::new() 510 | } 511 | 512 | fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor { 513 | static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy { 514 | lock: ::protobuf::lazy::ONCE_INIT, 515 | ptr: 0 as *const ::protobuf::reflect::MessageDescriptor, 516 | }; 517 | unsafe { 518 | descriptor.get(|| { 519 | let mut fields = ::std::vec::Vec::new(); 520 | fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<::protobuf::well_known_types::Timestamp>>( 521 | "time", 522 | |m: &response| { &m.time }, 523 | |m: &mut response| { &mut m.time }, 524 | )); 525 | fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( 526 | "priority", 527 | |m: &response| { &m.priority }, 528 | |m: &mut response| { &mut m.priority }, 529 | )); 530 | fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum>( 531 | "source", 532 | |m: &response| { &m.source }, 533 | |m: &mut response| { &mut m.source }, 534 | )); 535 | fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( 536 | "rule", 537 | |m: &response| { &m.rule }, 538 | |m: &mut response| { &mut m.rule }, 539 | )); 540 | fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( 541 | "output", 542 | |m: &response| { &m.output }, 543 | |m: &mut response| { &mut m.output }, 544 | )); 545 | fields.push(::protobuf::reflect::accessor::make_map_accessor::<_, ::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeString>( 546 | "output_fields", 547 | |m: &response| { &m.output_fields }, 548 | |m: &mut response| { &mut m.output_fields }, 549 | )); 550 | fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>( 551 | "hostname", 552 | |m: &response| { &m.hostname }, 553 | |m: &mut response| { &mut m.hostname }, 554 | )); 555 | ::protobuf::reflect::MessageDescriptor::new::( 556 | "response", 557 | fields, 558 | file_descriptor_proto() 559 | ) 560 | }) 561 | } 562 | } 563 | 564 | fn default_instance() -> &'static response { 565 | static mut instance: ::protobuf::lazy::Lazy = ::protobuf::lazy::Lazy { 566 | lock: ::protobuf::lazy::ONCE_INIT, 567 | ptr: 0 as *const response, 568 | }; 569 | unsafe { 570 | instance.get(response::new) 571 | } 572 | } 573 | } 574 | 575 | impl ::protobuf::Clear for response { 576 | fn clear(&mut self) { 577 | self.time.clear(); 578 | self.priority = super::schema::priority::EMERGENCY; 579 | self.source = super::schema::source::SYSCALL; 580 | self.rule.clear(); 581 | self.output.clear(); 582 | self.output_fields.clear(); 583 | self.hostname.clear(); 584 | self.unknown_fields.clear(); 585 | } 586 | } 587 | 588 | impl ::std::fmt::Debug for response { 589 | fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { 590 | ::protobuf::text_format::fmt(self, f) 591 | } 592 | } 593 | 594 | impl ::protobuf::reflect::ProtobufValue for response { 595 | fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { 596 | ::protobuf::reflect::ProtobufValueRef::Message(self) 597 | } 598 | } 599 | 600 | static file_descriptor_proto_data: &'static [u8] = b"\ 601 | \n\x0coutput.proto\x12\x0cfalco.output\x1a\x1fgoogle/protobuf/timestamp.\ 602 | proto\x1a\x0cschema.proto\"'\n\x07request\x12\x1c\n\tkeepalive\x18\x01\ 603 | \x20\x01(\x08R\tkeepalive\"\xf4\x02\n\x08response\x12.\n\x04time\x18\x01\ 604 | \x20\x01(\x0b2\x1a.google.protobuf.TimestampR\x04time\x122\n\x08priority\ 605 | \x18\x02\x20\x01(\x0e2\x16.falco.schema.priorityR\x08priority\x12,\n\x06\ 606 | source\x18\x03\x20\x01(\x0e2\x14.falco.schema.sourceR\x06source\x12\x12\ 607 | \n\x04rule\x18\x04\x20\x01(\tR\x04rule\x12\x16\n\x06output\x18\x05\x20\ 608 | \x01(\tR\x06output\x12M\n\routput_fields\x18\x06\x20\x03(\x0b2(.falco.ou\ 609 | tput.response.OutputFieldsEntryR\x0coutputFields\x12\x1a\n\x08hostname\ 610 | \x18\x07\x20\x01(\tR\x08hostname\x1a?\n\x11OutputFieldsEntry\x12\x10\n\ 611 | \x03key\x18\x01\x20\x01(\tR\x03key\x12\x14\n\x05value\x18\x02\x20\x01(\t\ 612 | R\x05value:\x028\x012G\n\x07service\x12<\n\tsubscribe\x12\x15.falco.outp\ 613 | ut.request\x1a\x16.falco.output.response0\x01J\xd5\r\n\x06\x12\x04\0\0&\ 614 | \x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\t\n\x02\x03\0\x12\x03\x02\0)\n\t\ 615 | \n\x02\x03\x01\x12\x03\x03\0\x16\n\x08\n\x01\x02\x12\x03\x05\0\x15\n\x8a\ 616 | \x01\n\x02\x06\0\x12\x04\n\0\x0c\x01\x1a~\x20The\x20`subscribe`\x20servi\ 617 | ce\x20defines\x20the\x20RPC\x20call\n\x20to\x20perform\x20an\x20output\ 618 | \x20`request`\x20which\x20will\x20lead\x20to\x20obtain\x20an\x20output\ 619 | \x20`response`.\n\n\n\n\x03\x06\0\x01\x12\x03\n\x08\x0f\n\x0b\n\x04\x06\ 620 | \0\x02\0\x12\x03\x0b\x023\n\x0c\n\x05\x06\0\x02\0\x01\x12\x03\x0b\x06\ 621 | \x0f\n\x0c\n\x05\x06\0\x02\0\x02\x12\x03\x0b\x10\x17\n\x0c\n\x05\x06\0\ 622 | \x02\0\x06\x12\x03\x0b\"(\n\x0c\n\x05\x06\0\x02\0\x03\x12\x03\x0b)1\n\ 623 | \x89\x03\n\x02\x04\0\x12\x04\x14\0\x18\x01\x1a\xfc\x02\x20The\x20`reques\ 624 | t`\x20message\x20is\x20the\x20logical\x20representation\x20of\x20the\x20\ 625 | request\x20model.\n\x20It\x20is\x20the\x20input\x20of\x20the\x20`subscri\ 626 | be`\x20service.\n\x20It\x20is\x20used\x20to\x20configure\x20the\x20kind\ 627 | \x20of\x20subscription\x20to\x20the\x20gRPC\x20streaming\x20server.\n\n\ 628 | \x20By\x20default\x20the\x20request\x20asks\x20to\x20the\x20server\x20to\ 629 | \x20only\x20receive\x20the\x20accumulated\x20events.\n\x20In\x20case\x20\ 630 | you\x20want\x20to\x20wait\x20indefinitely\x20for\x20new\x20events\x20to\ 631 | \x20come\x20set\x20the\x20keepalive\x20option\x20to\x20true.\n\n\n\n\x03\ 632 | \x04\0\x01\x12\x03\x14\x08\x0f\n\xc9\x01\n\x04\x04\0\x02\0\x12\x03\x15\ 633 | \x02\x15\"\xbb\x01\x20string\x20duration\x20=\x202;\x20//\x20TODO(leodid\ 634 | o,\x20fntlnz):\x20not\x20handled\x20yet\x20but\x20keeping\x20for\x20refe\ 635 | rence.\n\x20repeated\x20string\x20tags\x20=\x203;\x20//\x20TODO(leodido,\ 636 | \x20fntlnz):\x20not\x20handled\x20yet\x20but\x20keeping\x20for\x20refere\ 637 | nce.\n\n\r\n\x05\x04\0\x02\0\x04\x12\x04\x15\x02\x14\x11\n\x0c\n\x05\x04\ 638 | \0\x02\0\x05\x12\x03\x15\x02\x06\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x15\ 639 | \x07\x10\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x15\x13\x14\n\xcb\x01\n\x02\ 640 | \x04\x01\x12\x04\x1d\0&\x01\x1a\xbe\x01\x20The\x20`response`\x20message\ 641 | \x20is\x20the\x20logical\x20representation\x20of\x20the\x20output\x20mod\ 642 | el.\n\x20It\x20contains\x20all\x20the\x20elements\x20that\x20Falco\x20em\ 643 | its\x20in\x20an\x20output\x20along\x20with\x20the\n\x20definitions\x20fo\ 644 | r\x20priorities\x20and\x20source.\n\n\n\n\x03\x04\x01\x01\x12\x03\x1d\ 645 | \x08\x10\n\x0b\n\x04\x04\x01\x02\0\x12\x03\x1e\x02%\n\r\n\x05\x04\x01\ 646 | \x02\0\x04\x12\x04\x1e\x02\x1d\x12\n\x0c\n\x05\x04\x01\x02\0\x06\x12\x03\ 647 | \x1e\x02\x1b\n\x0c\n\x05\x04\x01\x02\0\x01\x12\x03\x1e\x1c\x20\n\x0c\n\ 648 | \x05\x04\x01\x02\0\x03\x12\x03\x1e#$\n\x0b\n\x04\x04\x01\x02\x01\x12\x03\ 649 | \x1f\x02%\n\r\n\x05\x04\x01\x02\x01\x04\x12\x04\x1f\x02\x1e%\n\x0c\n\x05\ 650 | \x04\x01\x02\x01\x06\x12\x03\x1f\x02\x17\n\x0c\n\x05\x04\x01\x02\x01\x01\ 651 | \x12\x03\x1f\x18\x20\n\x0c\n\x05\x04\x01\x02\x01\x03\x12\x03\x1f#$\n\x0b\ 652 | \n\x04\x04\x01\x02\x02\x12\x03\x20\x02!\n\r\n\x05\x04\x01\x02\x02\x04\ 653 | \x12\x04\x20\x02\x1f%\n\x0c\n\x05\x04\x01\x02\x02\x06\x12\x03\x20\x02\ 654 | \x15\n\x0c\n\x05\x04\x01\x02\x02\x01\x12\x03\x20\x16\x1c\n\x0c\n\x05\x04\ 655 | \x01\x02\x02\x03\x12\x03\x20\x1f\x20\n\x0b\n\x04\x04\x01\x02\x03\x12\x03\ 656 | !\x02\x12\n\r\n\x05\x04\x01\x02\x03\x04\x12\x04!\x02\x20!\n\x0c\n\x05\ 657 | \x04\x01\x02\x03\x05\x12\x03!\x02\x08\n\x0c\n\x05\x04\x01\x02\x03\x01\ 658 | \x12\x03!\t\r\n\x0c\n\x05\x04\x01\x02\x03\x03\x12\x03!\x10\x11\n\x0b\n\ 659 | \x04\x04\x01\x02\x04\x12\x03\"\x02\x14\n\r\n\x05\x04\x01\x02\x04\x04\x12\ 660 | \x04\"\x02!\x12\n\x0c\n\x05\x04\x01\x02\x04\x05\x12\x03\"\x02\x08\n\x0c\ 661 | \n\x05\x04\x01\x02\x04\x01\x12\x03\"\t\x0f\n\x0c\n\x05\x04\x01\x02\x04\ 662 | \x03\x12\x03\"\x12\x13\n\x0b\n\x04\x04\x01\x02\x05\x12\x03#\x02(\n\r\n\ 663 | \x05\x04\x01\x02\x05\x04\x12\x04#\x02\"\x14\n\x0c\n\x05\x04\x01\x02\x05\ 664 | \x06\x12\x03#\x02\x15\n\x0c\n\x05\x04\x01\x02\x05\x01\x12\x03#\x16#\n\ 665 | \x0c\n\x05\x04\x01\x02\x05\x03\x12\x03#&'\no\n\x04\x04\x01\x02\x06\x12\ 666 | \x03$\x02\x16\"b\x20repeated\x20string\x20tags\x20=\x208;\x20//\x20TODO(\ 667 | leodido,fntlnz):\x20tags\x20not\x20supported\x20yet,\x20keeping\x20for\ 668 | \x20reference\n\n\r\n\x05\x04\x01\x02\x06\x04\x12\x04$\x02#(\n\x0c\n\x05\ 669 | \x04\x01\x02\x06\x05\x12\x03$\x02\x08\n\x0c\n\x05\x04\x01\x02\x06\x01\ 670 | \x12\x03$\t\x11\n\x0c\n\x05\x04\x01\x02\x06\x03\x12\x03$\x14\x15b\x06pro\ 671 | to3\ 672 | "; 673 | 674 | static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy { 675 | lock: ::protobuf::lazy::ONCE_INIT, 676 | ptr: 0 as *const ::protobuf::descriptor::FileDescriptorProto, 677 | }; 678 | 679 | fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto { 680 | ::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap() 681 | } 682 | 683 | pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto { 684 | unsafe { 685 | file_descriptor_proto_lazy.get(|| { 686 | parse_descriptor_proto() 687 | }) 688 | } 689 | } 690 | -------------------------------------------------------------------------------- /src/api/output_grpc.rs: -------------------------------------------------------------------------------- 1 | // This file is generated. Do not edit 2 | // @generated 3 | 4 | // https://github.com/rust-lang/rust-clippy/issues/702 5 | #![allow(unknown_lints)] 6 | #![allow(clippy::all)] 7 | 8 | #![cfg_attr(rustfmt, rustfmt_skip)] 9 | 10 | #![allow(box_pointers)] 11 | #![allow(dead_code)] 12 | #![allow(missing_docs)] 13 | #![allow(non_camel_case_types)] 14 | #![allow(non_snake_case)] 15 | #![allow(non_upper_case_globals)] 16 | #![allow(trivial_casts)] 17 | #![allow(unsafe_code)] 18 | #![allow(unused_imports)] 19 | #![allow(unused_results)] 20 | 21 | const METHOD_SERVICE_SUBSCRIBE: ::grpcio::Method = ::grpcio::Method { 22 | ty: ::grpcio::MethodType::ServerStreaming, 23 | name: "/falco.output.service/subscribe", 24 | req_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, 25 | resp_mar: ::grpcio::Marshaller { ser: ::grpcio::pb_ser, de: ::grpcio::pb_de }, 26 | }; 27 | 28 | #[derive(Clone)] 29 | pub struct ServiceClient { 30 | client: ::grpcio::Client, 31 | } 32 | 33 | impl ServiceClient { 34 | pub fn new(channel: ::grpcio::Channel) -> Self { 35 | ServiceClient { 36 | client: ::grpcio::Client::new(channel), 37 | } 38 | } 39 | 40 | pub fn subscribe_opt(&self, req: &super::output::request, opt: ::grpcio::CallOption) -> ::grpcio::Result<::grpcio::ClientSStreamReceiver> { 41 | self.client.server_streaming(&METHOD_SERVICE_SUBSCRIBE, req, opt) 42 | } 43 | 44 | pub fn subscribe(&self, req: &super::output::request) -> ::grpcio::Result<::grpcio::ClientSStreamReceiver> { 45 | self.subscribe_opt(req, ::grpcio::CallOption::default()) 46 | } 47 | pub fn spawn(&self, f: F) where F: ::futures::Future + Send + 'static { 48 | self.client.spawn(f) 49 | } 50 | } 51 | 52 | pub trait Service { 53 | fn subscribe(&mut self, ctx: ::grpcio::RpcContext, req: super::output::request, sink: ::grpcio::ServerStreamingSink); 54 | } 55 | 56 | pub fn create_service(s: S) -> ::grpcio::Service { 57 | let mut builder = ::grpcio::ServiceBuilder::new(); 58 | let mut instance = s.clone(); 59 | builder = builder.add_server_streaming_handler(&METHOD_SERVICE_SUBSCRIBE, move |ctx, req, resp| { 60 | instance.subscribe(ctx, req, resp) 61 | }); 62 | builder.build() 63 | } 64 | -------------------------------------------------------------------------------- /src/api/schema.rs: -------------------------------------------------------------------------------- 1 | // This file is generated by rust-protobuf 2.10.1. Do not edit 2 | // @generated 3 | 4 | // https://github.com/rust-lang/rust-clippy/issues/702 5 | #![allow(unknown_lints)] 6 | #![allow(clippy::all)] 7 | 8 | #![cfg_attr(rustfmt, rustfmt_skip)] 9 | 10 | #![allow(box_pointers)] 11 | #![allow(dead_code)] 12 | #![allow(missing_docs)] 13 | #![allow(non_camel_case_types)] 14 | #![allow(non_snake_case)] 15 | #![allow(non_upper_case_globals)] 16 | #![allow(trivial_casts)] 17 | #![allow(unsafe_code)] 18 | #![allow(unused_imports)] 19 | #![allow(unused_results)] 20 | //! Generated file from `schema.proto` 21 | 22 | use protobuf::Message as Message_imported_for_functions; 23 | use protobuf::ProtobufEnum as ProtobufEnum_imported_for_functions; 24 | 25 | /// Generated files are compatible only with the same version 26 | /// of protobuf runtime. 27 | // const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_10_1; 28 | 29 | // Note: you cannot use pattern matching for enums with allow_alias option 30 | #[derive(Clone,Eq,Debug)] 31 | pub enum priority { 32 | EMERGENCY, // 0 33 | emergency, // 0 34 | Emergency, // 0 35 | ALERT, // 1 36 | alert, // 1 37 | Alert, // 1 38 | CRITICAL, // 2 39 | critical, // 2 40 | Critical, // 2 41 | ERROR, // 3 42 | error, // 3 43 | Error, // 3 44 | WARNING, // 4 45 | warning, // 4 46 | Warning, // 4 47 | NOTICE, // 5 48 | notice, // 5 49 | Notice, // 5 50 | INFORMATIONAL, // 6 51 | informational, // 6 52 | Informational, // 6 53 | DEBUG, // 7 54 | debug, // 7 55 | Debug, // 7 56 | } 57 | 58 | impl ::std::cmp::PartialEq for priority { 59 | fn eq(&self, other: &Self) -> bool { 60 | self.value() == other.value() 61 | } 62 | } 63 | 64 | impl ::std::hash::Hash for priority { 65 | fn hash(&self, state: &mut H) { 66 | state.write_i32(self.value()) 67 | } 68 | } 69 | 70 | impl ::protobuf::ProtobufEnum for priority { 71 | fn value(&self) -> i32 { 72 | match *self { 73 | priority::EMERGENCY => 0, 74 | priority::emergency => 0, 75 | priority::Emergency => 0, 76 | priority::ALERT => 1, 77 | priority::alert => 1, 78 | priority::Alert => 1, 79 | priority::CRITICAL => 2, 80 | priority::critical => 2, 81 | priority::Critical => 2, 82 | priority::ERROR => 3, 83 | priority::error => 3, 84 | priority::Error => 3, 85 | priority::WARNING => 4, 86 | priority::warning => 4, 87 | priority::Warning => 4, 88 | priority::NOTICE => 5, 89 | priority::notice => 5, 90 | priority::Notice => 5, 91 | priority::INFORMATIONAL => 6, 92 | priority::informational => 6, 93 | priority::Informational => 6, 94 | priority::DEBUG => 7, 95 | priority::debug => 7, 96 | priority::Debug => 7, 97 | } 98 | } 99 | 100 | fn from_i32(value: i32) -> ::std::option::Option { 101 | match value { 102 | 0 => ::std::option::Option::Some(priority::EMERGENCY), 103 | 1 => ::std::option::Option::Some(priority::ALERT), 104 | 2 => ::std::option::Option::Some(priority::CRITICAL), 105 | 3 => ::std::option::Option::Some(priority::ERROR), 106 | 4 => ::std::option::Option::Some(priority::WARNING), 107 | 5 => ::std::option::Option::Some(priority::NOTICE), 108 | 6 => ::std::option::Option::Some(priority::INFORMATIONAL), 109 | 7 => ::std::option::Option::Some(priority::DEBUG), 110 | _ => ::std::option::Option::None 111 | } 112 | } 113 | 114 | fn values() -> &'static [Self] { 115 | static values: &'static [priority] = &[ 116 | priority::EMERGENCY, 117 | priority::emergency, 118 | priority::Emergency, 119 | priority::ALERT, 120 | priority::alert, 121 | priority::Alert, 122 | priority::CRITICAL, 123 | priority::critical, 124 | priority::Critical, 125 | priority::ERROR, 126 | priority::error, 127 | priority::Error, 128 | priority::WARNING, 129 | priority::warning, 130 | priority::Warning, 131 | priority::NOTICE, 132 | priority::notice, 133 | priority::Notice, 134 | priority::INFORMATIONAL, 135 | priority::informational, 136 | priority::Informational, 137 | priority::DEBUG, 138 | priority::debug, 139 | priority::Debug, 140 | ]; 141 | values 142 | } 143 | 144 | fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor { 145 | static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::EnumDescriptor> = ::protobuf::lazy::Lazy { 146 | lock: ::protobuf::lazy::ONCE_INIT, 147 | ptr: 0 as *const ::protobuf::reflect::EnumDescriptor, 148 | }; 149 | unsafe { 150 | descriptor.get(|| { 151 | ::protobuf::reflect::EnumDescriptor::new("priority", file_descriptor_proto()) 152 | }) 153 | } 154 | } 155 | } 156 | 157 | impl ::std::marker::Copy for priority { 158 | } 159 | 160 | impl ::std::default::Default for priority { 161 | fn default() -> Self { 162 | priority::EMERGENCY 163 | } 164 | } 165 | 166 | impl ::protobuf::reflect::ProtobufValue for priority { 167 | fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { 168 | ::protobuf::reflect::ProtobufValueRef::Enum(self.descriptor()) 169 | } 170 | } 171 | 172 | // Note: you cannot use pattern matching for enums with allow_alias option 173 | #[derive(Clone,Eq,Debug)] 174 | pub enum source { 175 | SYSCALL, // 0 176 | syscall, // 0 177 | Syscall, // 0 178 | K8S_AUDIT, // 1 179 | k8s_audit, // 1 180 | K8s_audit, // 1 181 | K8S_audit, // 1 182 | } 183 | 184 | impl ::std::cmp::PartialEq for source { 185 | fn eq(&self, other: &Self) -> bool { 186 | self.value() == other.value() 187 | } 188 | } 189 | 190 | impl ::std::hash::Hash for source { 191 | fn hash(&self, state: &mut H) { 192 | state.write_i32(self.value()) 193 | } 194 | } 195 | 196 | impl ::protobuf::ProtobufEnum for source { 197 | fn value(&self) -> i32 { 198 | match *self { 199 | source::SYSCALL => 0, 200 | source::syscall => 0, 201 | source::Syscall => 0, 202 | source::K8S_AUDIT => 1, 203 | source::k8s_audit => 1, 204 | source::K8s_audit => 1, 205 | source::K8S_audit => 1, 206 | } 207 | } 208 | 209 | fn from_i32(value: i32) -> ::std::option::Option { 210 | match value { 211 | 0 => ::std::option::Option::Some(source::SYSCALL), 212 | 1 => ::std::option::Option::Some(source::K8S_AUDIT), 213 | _ => ::std::option::Option::None 214 | } 215 | } 216 | 217 | fn values() -> &'static [Self] { 218 | static values: &'static [source] = &[ 219 | source::SYSCALL, 220 | source::syscall, 221 | source::Syscall, 222 | source::K8S_AUDIT, 223 | source::k8s_audit, 224 | source::K8s_audit, 225 | source::K8S_audit, 226 | ]; 227 | values 228 | } 229 | 230 | fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor { 231 | static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::EnumDescriptor> = ::protobuf::lazy::Lazy { 232 | lock: ::protobuf::lazy::ONCE_INIT, 233 | ptr: 0 as *const ::protobuf::reflect::EnumDescriptor, 234 | }; 235 | unsafe { 236 | descriptor.get(|| { 237 | ::protobuf::reflect::EnumDescriptor::new("source", file_descriptor_proto()) 238 | }) 239 | } 240 | } 241 | } 242 | 243 | impl ::std::marker::Copy for source { 244 | } 245 | 246 | impl ::std::default::Default for source { 247 | fn default() -> Self { 248 | source::SYSCALL 249 | } 250 | } 251 | 252 | impl ::protobuf::reflect::ProtobufValue for source { 253 | fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef { 254 | ::protobuf::reflect::ProtobufValueRef::Enum(self.descriptor()) 255 | } 256 | } 257 | 258 | static file_descriptor_proto_data: &'static [u8] = b"\ 259 | \n\x0cschema.proto\x12\x0cfalco.schema*\xcc\x02\n\x08priority\x12\r\n\tE\ 260 | MERGENCY\x10\0\x12\r\n\temergency\x10\0\x12\r\n\tEmergency\x10\0\x12\t\n\ 261 | \x05ALERT\x10\x01\x12\t\n\x05alert\x10\x01\x12\t\n\x05Alert\x10\x01\x12\ 262 | \x0c\n\x08CRITICAL\x10\x02\x12\x0c\n\x08critical\x10\x02\x12\x0c\n\x08Cr\ 263 | itical\x10\x02\x12\t\n\x05ERROR\x10\x03\x12\t\n\x05error\x10\x03\x12\t\n\ 264 | \x05Error\x10\x03\x12\x0b\n\x07WARNING\x10\x04\x12\x0b\n\x07warning\x10\ 265 | \x04\x12\x0b\n\x07Warning\x10\x04\x12\n\n\x06NOTICE\x10\x05\x12\n\n\x06n\ 266 | otice\x10\x05\x12\n\n\x06Notice\x10\x05\x12\x11\n\rINFORMATIONAL\x10\x06\ 267 | \x12\x11\n\rinformational\x10\x06\x12\x11\n\rInformational\x10\x06\x12\t\ 268 | \n\x05DEBUG\x10\x07\x12\t\n\x05debug\x10\x07\x12\t\n\x05Debug\x10\x07\ 269 | \x1a\x02\x10\x01*o\n\x06source\x12\x0b\n\x07SYSCALL\x10\0\x12\x0b\n\x07s\ 270 | yscall\x10\0\x12\x0b\n\x07Syscall\x10\0\x12\r\n\tK8S_AUDIT\x10\x01\x12\r\ 271 | \n\tk8s_audit\x10\x01\x12\r\n\tK8s_audit\x10\x01\x12\r\n\tK8S_audit\x10\ 272 | \x01\x1a\x02\x10\x01J\xf5\n\n\x06\x12\x04\0\0*\x01\n\x08\n\x01\x0c\x12\ 273 | \x03\0\0\x12\n\x08\n\x01\x02\x12\x03\x02\0\x15\n\n\n\x02\x05\0\x12\x04\ 274 | \x05\0\x1f\x01\n\n\n\x03\x05\0\x01\x12\x03\x05\x05\r\n\n\n\x03\x05\0\x03\ 275 | \x12\x03\x06\x02\x1c\n\x0b\n\x04\x05\0\x03\x02\x12\x03\x06\x02\x1c\n\x0b\ 276 | \n\x04\x05\0\x02\0\x12\x03\x07\x02\x10\n\x0c\n\x05\x05\0\x02\0\x01\x12\ 277 | \x03\x07\x02\x0b\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x07\x0e\x0f\n\x0b\n\ 278 | \x04\x05\0\x02\x01\x12\x03\x08\x02\x10\n\x0c\n\x05\x05\0\x02\x01\x01\x12\ 279 | \x03\x08\x02\x0b\n\x0c\n\x05\x05\0\x02\x01\x02\x12\x03\x08\x0e\x0f\n\x0b\ 280 | \n\x04\x05\0\x02\x02\x12\x03\t\x02\x10\n\x0c\n\x05\x05\0\x02\x02\x01\x12\ 281 | \x03\t\x02\x0b\n\x0c\n\x05\x05\0\x02\x02\x02\x12\x03\t\x0e\x0f\n\x0b\n\ 282 | \x04\x05\0\x02\x03\x12\x03\n\x02\x0c\n\x0c\n\x05\x05\0\x02\x03\x01\x12\ 283 | \x03\n\x02\x07\n\x0c\n\x05\x05\0\x02\x03\x02\x12\x03\n\n\x0b\n\x0b\n\x04\ 284 | \x05\0\x02\x04\x12\x03\x0b\x02\x0c\n\x0c\n\x05\x05\0\x02\x04\x01\x12\x03\ 285 | \x0b\x02\x07\n\x0c\n\x05\x05\0\x02\x04\x02\x12\x03\x0b\n\x0b\n\x0b\n\x04\ 286 | \x05\0\x02\x05\x12\x03\x0c\x02\x0c\n\x0c\n\x05\x05\0\x02\x05\x01\x12\x03\ 287 | \x0c\x02\x07\n\x0c\n\x05\x05\0\x02\x05\x02\x12\x03\x0c\n\x0b\n\x0b\n\x04\ 288 | \x05\0\x02\x06\x12\x03\r\x02\x0f\n\x0c\n\x05\x05\0\x02\x06\x01\x12\x03\r\ 289 | \x02\n\n\x0c\n\x05\x05\0\x02\x06\x02\x12\x03\r\r\x0e\n\x0b\n\x04\x05\0\ 290 | \x02\x07\x12\x03\x0e\x02\x0f\n\x0c\n\x05\x05\0\x02\x07\x01\x12\x03\x0e\ 291 | \x02\n\n\x0c\n\x05\x05\0\x02\x07\x02\x12\x03\x0e\r\x0e\n\x0b\n\x04\x05\0\ 292 | \x02\x08\x12\x03\x0f\x02\x0f\n\x0c\n\x05\x05\0\x02\x08\x01\x12\x03\x0f\ 293 | \x02\n\n\x0c\n\x05\x05\0\x02\x08\x02\x12\x03\x0f\r\x0e\n\x0b\n\x04\x05\0\ 294 | \x02\t\x12\x03\x10\x02\x0c\n\x0c\n\x05\x05\0\x02\t\x01\x12\x03\x10\x02\ 295 | \x07\n\x0c\n\x05\x05\0\x02\t\x02\x12\x03\x10\n\x0b\n\x0b\n\x04\x05\0\x02\ 296 | \n\x12\x03\x11\x02\x0c\n\x0c\n\x05\x05\0\x02\n\x01\x12\x03\x11\x02\x07\n\ 297 | \x0c\n\x05\x05\0\x02\n\x02\x12\x03\x11\n\x0b\n\x0b\n\x04\x05\0\x02\x0b\ 298 | \x12\x03\x12\x02\x0c\n\x0c\n\x05\x05\0\x02\x0b\x01\x12\x03\x12\x02\x07\n\ 299 | \x0c\n\x05\x05\0\x02\x0b\x02\x12\x03\x12\n\x0b\n\x0b\n\x04\x05\0\x02\x0c\ 300 | \x12\x03\x13\x02\x0e\n\x0c\n\x05\x05\0\x02\x0c\x01\x12\x03\x13\x02\t\n\ 301 | \x0c\n\x05\x05\0\x02\x0c\x02\x12\x03\x13\x0c\r\n\x0b\n\x04\x05\0\x02\r\ 302 | \x12\x03\x14\x02\x0e\n\x0c\n\x05\x05\0\x02\r\x01\x12\x03\x14\x02\t\n\x0c\ 303 | \n\x05\x05\0\x02\r\x02\x12\x03\x14\x0c\r\n\x0b\n\x04\x05\0\x02\x0e\x12\ 304 | \x03\x15\x02\x0e\n\x0c\n\x05\x05\0\x02\x0e\x01\x12\x03\x15\x02\t\n\x0c\n\ 305 | \x05\x05\0\x02\x0e\x02\x12\x03\x15\x0c\r\n\x0b\n\x04\x05\0\x02\x0f\x12\ 306 | \x03\x16\x02\r\n\x0c\n\x05\x05\0\x02\x0f\x01\x12\x03\x16\x02\x08\n\x0c\n\ 307 | \x05\x05\0\x02\x0f\x02\x12\x03\x16\x0b\x0c\n\x0b\n\x04\x05\0\x02\x10\x12\ 308 | \x03\x17\x02\r\n\x0c\n\x05\x05\0\x02\x10\x01\x12\x03\x17\x02\x08\n\x0c\n\ 309 | \x05\x05\0\x02\x10\x02\x12\x03\x17\x0b\x0c\n\x0b\n\x04\x05\0\x02\x11\x12\ 310 | \x03\x18\x02\r\n\x0c\n\x05\x05\0\x02\x11\x01\x12\x03\x18\x02\x08\n\x0c\n\ 311 | \x05\x05\0\x02\x11\x02\x12\x03\x18\x0b\x0c\n\x0b\n\x04\x05\0\x02\x12\x12\ 312 | \x03\x19\x02\x14\n\x0c\n\x05\x05\0\x02\x12\x01\x12\x03\x19\x02\x0f\n\x0c\ 313 | \n\x05\x05\0\x02\x12\x02\x12\x03\x19\x12\x13\n\x0b\n\x04\x05\0\x02\x13\ 314 | \x12\x03\x1a\x02\x14\n\x0c\n\x05\x05\0\x02\x13\x01\x12\x03\x1a\x02\x0f\n\ 315 | \x0c\n\x05\x05\0\x02\x13\x02\x12\x03\x1a\x12\x13\n\x0b\n\x04\x05\0\x02\ 316 | \x14\x12\x03\x1b\x02\x14\n\x0c\n\x05\x05\0\x02\x14\x01\x12\x03\x1b\x02\ 317 | \x0f\n\x0c\n\x05\x05\0\x02\x14\x02\x12\x03\x1b\x12\x13\n\x0b\n\x04\x05\0\ 318 | \x02\x15\x12\x03\x1c\x02\x0c\n\x0c\n\x05\x05\0\x02\x15\x01\x12\x03\x1c\ 319 | \x02\x07\n\x0c\n\x05\x05\0\x02\x15\x02\x12\x03\x1c\n\x0b\n\x0b\n\x04\x05\ 320 | \0\x02\x16\x12\x03\x1d\x02\x0c\n\x0c\n\x05\x05\0\x02\x16\x01\x12\x03\x1d\ 321 | \x02\x07\n\x0c\n\x05\x05\0\x02\x16\x02\x12\x03\x1d\n\x0b\n\x0b\n\x04\x05\ 322 | \0\x02\x17\x12\x03\x1e\x02\x0c\n\x0c\n\x05\x05\0\x02\x17\x01\x12\x03\x1e\ 323 | \x02\x07\n\x0c\n\x05\x05\0\x02\x17\x02\x12\x03\x1e\n\x0b\n\n\n\x02\x05\ 324 | \x01\x12\x04!\0*\x01\n\n\n\x03\x05\x01\x01\x12\x03!\x05\x0b\n\n\n\x03\ 325 | \x05\x01\x03\x12\x03\"\x02\x1c\n\x0b\n\x04\x05\x01\x03\x02\x12\x03\"\x02\ 326 | \x1c\n\x0b\n\x04\x05\x01\x02\0\x12\x03#\x02\x0e\n\x0c\n\x05\x05\x01\x02\ 327 | \0\x01\x12\x03#\x02\t\n\x0c\n\x05\x05\x01\x02\0\x02\x12\x03#\x0c\r\n\x0b\ 328 | \n\x04\x05\x01\x02\x01\x12\x03$\x02\x0e\n\x0c\n\x05\x05\x01\x02\x01\x01\ 329 | \x12\x03$\x02\t\n\x0c\n\x05\x05\x01\x02\x01\x02\x12\x03$\x0c\r\n\x0b\n\ 330 | \x04\x05\x01\x02\x02\x12\x03%\x02\x0e\n\x0c\n\x05\x05\x01\x02\x02\x01\ 331 | \x12\x03%\x02\t\n\x0c\n\x05\x05\x01\x02\x02\x02\x12\x03%\x0c\r\n\x0b\n\ 332 | \x04\x05\x01\x02\x03\x12\x03&\x02\x10\n\x0c\n\x05\x05\x01\x02\x03\x01\ 333 | \x12\x03&\x02\x0b\n\x0c\n\x05\x05\x01\x02\x03\x02\x12\x03&\x0e\x0f\n\x0b\ 334 | \n\x04\x05\x01\x02\x04\x12\x03'\x02\x10\n\x0c\n\x05\x05\x01\x02\x04\x01\ 335 | \x12\x03'\x02\x0b\n\x0c\n\x05\x05\x01\x02\x04\x02\x12\x03'\x0e\x0f\n\x0b\ 336 | \n\x04\x05\x01\x02\x05\x12\x03(\x02\x10\n\x0c\n\x05\x05\x01\x02\x05\x01\ 337 | \x12\x03(\x02\x0b\n\x0c\n\x05\x05\x01\x02\x05\x02\x12\x03(\x0e\x0f\n\x0b\ 338 | \n\x04\x05\x01\x02\x06\x12\x03)\x02\x10\n\x0c\n\x05\x05\x01\x02\x06\x01\ 339 | \x12\x03)\x02\x0b\n\x0c\n\x05\x05\x01\x02\x06\x02\x12\x03)\x0e\x0fb\x06p\ 340 | roto3\ 341 | "; 342 | 343 | static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy { 344 | lock: ::protobuf::lazy::ONCE_INIT, 345 | ptr: 0 as *const ::protobuf::descriptor::FileDescriptorProto, 346 | }; 347 | 348 | fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto { 349 | ::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap() 350 | } 351 | 352 | pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto { 353 | unsafe { 354 | file_descriptor_proto_lazy.get(|| { 355 | parse_descriptor_proto() 356 | }) 357 | } 358 | } 359 | -------------------------------------------------------------------------------- /src/certs.rs: -------------------------------------------------------------------------------- 1 | use crate::{Result, ResultExt}; 2 | use std::{fs::File, io::Read, path::Path}; 3 | 4 | pub fn check_pem_file(path: &Path) -> Result { 5 | Ok(File::open(path).context(internal_err!("failed to open {}", path.display()))?) 6 | } 7 | 8 | pub fn load_pem_file(path: &Path) -> Result> { 9 | let mut file = check_pem_file(path)?; 10 | let mut key = vec![]; 11 | file.read_to_end(&mut key) 12 | .context(internal_err!("failed to open {}", path.display()))?; 13 | Ok(key) 14 | } 15 | -------------------------------------------------------------------------------- /src/client.rs: -------------------------------------------------------------------------------- 1 | use std::sync::Arc; 2 | 3 | use crate::api::output_grpc; 4 | use crate::{certs, config, Result}; 5 | use grpcio::{ChannelBuilder, ChannelCredentialsBuilder, Environment}; 6 | 7 | pub trait Connect { 8 | fn connect(env: Arc, config: config::Config) -> Result; 9 | } 10 | 11 | pub struct FalcoConnect { 12 | pub env: Arc, 13 | } 14 | 15 | impl Connect for FalcoConnect { 16 | fn connect(env: Arc, config: config::Config) -> Result { 17 | let auth = config 18 | .auth 19 | .as_ref() 20 | .ok_or(internal_err!("unencrypted connections are not supported"))?; 21 | 22 | let root_cert = certs::load_pem_file(auth.ca.as_ref())?; 23 | let client_cert = certs::load_pem_file(auth.cert.as_ref())?; 24 | let client_key = certs::load_pem_file(auth.key.as_ref())?; 25 | 26 | let credentials = ChannelCredentialsBuilder::new() 27 | // Set the PEM encoded server root cert to verify server's identity 28 | .root_cert(root_cert) 29 | // Set the PEM encoded client side cert and key 30 | .cert(client_cert, client_key) 31 | // Create channel credentials 32 | .build(); 33 | 34 | Ok(ChannelBuilder::new(env).secure_connect(config.endpoint.as_str(), credentials)) 35 | } 36 | } 37 | 38 | // TODO(fntlnz,leodido): make the completion queue configurable 39 | // TODO(fntlnz,leodido): keepalive, timeout, reconnect ? 40 | 41 | #[derive(Clone)] 42 | pub struct Client { 43 | channel: grpcio::Channel, 44 | } 45 | 46 | impl Client { 47 | pub fn new(config: config::Config) -> Result { 48 | let env = Arc::new(Environment::new(2)); 49 | let channel = FalcoConnect::connect(env, config)?; 50 | Ok(Client { channel }) 51 | } 52 | 53 | pub fn outputs(&self) -> output_grpc::ServiceClient { 54 | output_grpc::ServiceClient::new(self.channel.clone()) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/config.rs: -------------------------------------------------------------------------------- 1 | use serde_derive::{Deserialize, Serialize}; 2 | use std::default::Default; 3 | use std::path::PathBuf; 4 | 5 | #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] 6 | pub struct AuthConfig { 7 | pub(crate) ca: PathBuf, 8 | pub(crate) cert: PathBuf, 9 | pub(crate) key: PathBuf, 10 | } 11 | 12 | #[derive(Clone, Debug, Serialize, Deserialize, PartialEq)] 13 | #[serde(default)] 14 | #[serde(rename_all = "kebab-case")] 15 | pub struct Config { 16 | pub(crate) endpoint: String, 17 | #[serde(flatten)] 18 | pub(crate) auth: Option, 19 | } 20 | 21 | impl Config { 22 | /// Create a new [`Config`](Config) with the given Falco gRPC endpoint. 23 | /// 24 | /// ```rust 25 | /// use falco::config::Config; 26 | /// let config = Config::new("localhost:5060"); 27 | /// ``` 28 | pub fn new(endpoint: &str) -> Self { 29 | Config { 30 | endpoint: endpoint.into(), 31 | auth: None, 32 | } 33 | } 34 | 35 | /// Set the certificate authority, certificate, and key locations for the [`Config`](Config). 36 | /// 37 | /// This is required by default from the Falco gRPC server. 38 | /// 39 | /// ```rust 40 | /// use falco::config::Config; 41 | /// let config = Config::new("localhost:5060") 42 | /// .with_auth("ca.crt", "client.crt", "client.key"); 43 | /// ``` 44 | pub fn with_auth( 45 | mut self, 46 | ca: impl Into, 47 | cert: impl Into, 48 | key: impl Into, 49 | ) -> Self { 50 | self.auth = Some(AuthConfig { 51 | ca: ca.into(), 52 | cert: cert.into(), 53 | key: key.into(), 54 | }); 55 | self 56 | } 57 | } 58 | 59 | impl Default for Config { 60 | fn default() -> Self { 61 | Config { 62 | endpoint: "localhost:5060".to_owned(), 63 | auth: Some(AuthConfig { 64 | ca: PathBuf::from("/tmp/certs/ca.crt"), 65 | cert: PathBuf::from("/etc/certs/client.crt"), 66 | key: PathBuf::from("/etc/certs/client.key"), 67 | }), 68 | } 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/errors.rs: -------------------------------------------------------------------------------- 1 | use failure::{Context, Fail}; 2 | use std::result; 3 | 4 | pub use failure::ResultExt; 5 | 6 | #[derive(Debug, Fail)] 7 | pub enum ErrorKind { 8 | /// Wraps a `std::io::Error`. 9 | #[fail(display = "IO error: {}", _0)] 10 | Io(#[fail(cause)] std::io::Error), 11 | /// Wraps an internal message 12 | #[fail(display = "[{}:{}]: {}", file, line, message)] 13 | InternalError { 14 | file: String, 15 | line: u32, 16 | message: String, 17 | }, 18 | } 19 | 20 | impl ErrorKind { 21 | pub(crate) fn internal_error( 22 | file: impl Into, 23 | line: u32, 24 | message: impl Into, 25 | ) -> Self { 26 | ErrorKind::InternalError { 27 | file: file.into(), 28 | line, 29 | message: message.into(), 30 | } 31 | } 32 | } 33 | 34 | pub type Error = Context; 35 | 36 | /// Result with an error 37 | pub type Result = result::Result; 38 | 39 | #[cfg(test)] 40 | mod tests { 41 | #[test] 42 | fn test_internal_error_format() { 43 | let err = internal_err!("testing"); 44 | let err_str = err.to_string(); 45 | // yes, this is fragile 46 | assert_eq!(err_str, "[src/errors.rs:43]: testing"); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! This crate provides a clean, ready to use client for [Falco](https://github.com/falcosecurity/falco), a 2 | //! Cloud Native Runtime Security tool written in C++. 3 | //! 4 | //! With this crate you can easily connect to the Falco gRPC API, interact with it, receive the alerts, and ... 5 | //! 6 | 7 | #[macro_use] 8 | mod macros; 9 | #[macro_use] 10 | pub mod api; 11 | mod certs; 12 | pub mod client; 13 | pub mod config; 14 | mod errors; 15 | pub use crate::errors::Error; 16 | pub use crate::errors::ErrorKind; 17 | pub use crate::errors::Result; 18 | pub use crate::errors::ResultExt; // reexport of failure::ResultExt 19 | -------------------------------------------------------------------------------- /src/macros.rs: -------------------------------------------------------------------------------- 1 | macro_rules! internal_err { 2 | ($e:expr) => ({ 3 | $crate::ErrorKind::internal_error(file!(), line!(), $e) 4 | }); 5 | ($f:tt, $($arg:expr),+) => ({ 6 | internal_err!(format!($f, $($arg),+)) 7 | }); 8 | } 9 | --------------------------------------------------------------------------------