Compare commits
129 Commits
falco-incu
...
main
Author | SHA1 | Date |
---|---|---|
|
be3800132f | |
|
120881647a | |
|
d0be92e53e | |
|
488e6f8f0c | |
|
4d51b1813f | |
|
b4437c492f | |
|
cb17833316 | |
|
4ccf111c36 | |
|
ae6ed41a7a | |
|
277b28eb98 | |
|
4f6510b909 | |
|
6f8c46deb5 | |
|
f8fb73a3eb | |
|
3e74a466ae | |
|
15bb0fea8c | |
|
75a39c1dee | |
|
ce46d23f61 | |
|
371e43167e | |
|
8e4ed0c27d | |
|
1d2c6b1f0b | |
|
47843ac872 | |
|
740f8783e0 | |
|
4633f290ad | |
|
d8415c1bc1 | |
|
8eef0097ca | |
|
abf6637e0a | |
|
283a62f464 | |
|
407e99721f | |
|
e38fb3f6a7 | |
|
b6ad373719 | |
|
bd6d337f0e | |
|
baecf181ea | |
|
342b20dc7d | |
|
1d3cd24e81 | |
|
068f0f2dc9 | |
|
28b98b6f5f | |
|
c0a9bf17d5 | |
|
ea8f792589 | |
|
ea57e78ea1 | |
|
36f4320a46 | |
|
df963b6bcd | |
|
a81590059c | |
|
ad27109fa2 | |
|
679a50aa5c | |
|
9e56293b55 | |
|
59bf03bf74 | |
|
70b0d4f389 | |
|
95c822c595 | |
|
29c41c4eed | |
|
4f153f53ae | |
|
5ad584f200 | |
|
e65f2518b0 | |
|
ec255e68f4 | |
|
869c9a7f4d | |
|
88a40c8d9c | |
|
172d2c283f | |
|
d7a3895155 | |
|
354f9ea692 | |
|
9ba166cf44 | |
|
fbf0a4e8ce | |
|
44addef4f7 | |
|
acd08c4107 | |
|
f42e702682 | |
|
dc7970d175 | |
|
f88b991a7f | |
|
2ded9e2613 | |
|
623ee22a3e | |
|
b499a1d0d0 | |
|
497e01189e | |
|
b0497d597f | |
|
34bc909603 | |
|
0f609769ef | |
|
0afd6eace9 | |
|
8b480923cb | |
|
6ed2036d83 | |
|
1053b2d1b6 | |
|
3cac61cfa9 | |
|
3c82a97683 | |
|
3f982327dd | |
|
28bb5b019e | |
|
aabd1fbb6a | |
|
7c10902456 | |
|
fd892b78af | |
|
3f2202d3db | |
|
3f668d0568 | |
|
c39d31a0bc | |
|
c70d051893 | |
|
2ac430be13 | |
|
1221b9e817 | |
|
3178f6cd63 | |
|
bc15f2a29d | |
|
424b258789 | |
|
529b10a2a6 | |
|
cd33bc34af | |
|
195ae8297a | |
|
262f56986e | |
|
dd38952168 | |
|
447c809fde | |
|
eff31cab57 | |
|
abe601b7d8 | |
|
cad89fcf17 | |
|
4423b76267 | |
|
0afda1ffe1 | |
|
f373324498 | |
|
448d429ae4 | |
|
64e2adb309 | |
|
35a379a211 | |
|
29964b3cfa | |
|
8f0520fa09 | |
|
8e1ae009dc | |
|
e206c1a3f1 | |
|
177db2d421 | |
|
af9f206cce | |
|
5f42a381a7 | |
|
3a036f259f | |
|
a5dd5a26ad | |
|
a22d0d7a41 | |
|
82d7a935b5 | |
|
93310c5328 | |
|
d119706074 | |
|
2e1aed6cb2 | |
|
5f7d2e1ebc | |
|
1229c908e0 | |
|
e1bbf23ef5 | |
|
c366d5bd03 | |
|
ca4b012277 | |
|
7a7cf24f7d | |
|
77ba57ab2c | |
|
69c9be89d7 |
|
@ -1,2 +1,4 @@
|
|||
master
|
||||
0.36.0-rc2
|
||||
0.41.2
|
||||
0.41.1
|
||||
0.41.0
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "github-actions"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
open-pull-requests-limit: 10
|
||||
groups:
|
||||
actions:
|
||||
update-types:
|
||||
- "minor"
|
||||
- "patch"
|
|
@ -0,0 +1 @@
|
|||
3.12
|
|
@ -0,0 +1,11 @@
|
|||
[project]
|
||||
name = "scripts"
|
||||
version = "0.1.0"
|
||||
description = "GHA scripts to publish pages"
|
||||
readme = ""
|
||||
requires-python = ">=3.12"
|
||||
dependencies = [
|
||||
"pandas>=2.2.3",
|
||||
"pyyaml>=6.0.2",
|
||||
"tabulate>=0.9.0",
|
||||
]
|
|
@ -1,3 +0,0 @@
|
|||
pandas==2.0.3
|
||||
pyyaml===6.0.1
|
||||
tabulate==0.9.0
|
|
@ -96,13 +96,13 @@ def print_markdown(df):
|
|||
print('# Falco Rules Overview\n')
|
||||
print('Last Updated: {}\n'.format(datetime.date.today()))
|
||||
print('This auto-generated document is derived from the `falco*_rules.yaml` files within the [rules](https://github.com/falcosecurity/rules/blob/main/rules/) directory of the main branch in the official Falco [rules repository](https://github.com/falcosecurity/rules/tree/main).\n')
|
||||
print('The Falco project maintains a total of {} [rules](https://github.com/falcosecurity/rules/blob/main/rules/), of which {} rules are included in the default Falco package and labeled with [maturity_stable](https://github.com/falcosecurity/rules/blob/main/CONTRIBUTING.md#rules-maturity-framework). Rules at the remaining maturity levels may need extra customization to ensure effective adoption. Consequently, certain rules are intentionally disabled by default, irrespective of their maturity level.\n'.format(n_rules, len(df_stable)))
|
||||
print('The Falco Project manages a total of {} [rules](https://github.com/falcosecurity/rules/blob/main/rules/), of which {} rules are included in the Falco release package and labeled with [maturity_stable](https://github.com/falcosecurity/rules/blob/main/CONTRIBUTING.md#rules-maturity-framework). Rules at the remaining maturity levels require explicit installation and may need extra customization to ensure effective adoption. Lastly, certain rules are intentionally disabled by default, irrespective of their maturity level.\n'.format(n_rules, len(df_stable)))
|
||||
print('This document provides an extensive overview of community-contributed syscall and container event-based rules. It offers resources for learning about these rules, promoting successful adoption, and driving future enhancements.\n')
|
||||
print('\n[Stable Falco Rules](#stable-falco-rules) | [Incubating Falco Rules](#incubating-falco-rules) | [Sandbox Falco Rules](#sandbox-falco-rules) | [Deprecated Falco Rules](#deprecated-falco-rules) | [Falco Rules Stats](#falco-rules-stats)\n')
|
||||
print('\nThe tables below can be scrolled to the right.\n')
|
||||
|
||||
print('\n## Stable Falco Rules\n')
|
||||
print('\n{} stable Falco rules ({:.2f}% of rules) are enabled by default:\n'.format(len(df_stable), (100.0 * len(df_stable) / n_rules)))
|
||||
print('\n{} stable Falco rules ({:.2f}% of rules) are included in the Falco release package:\n'.format(len(df_stable), (100.0 * len(df_stable) / n_rules)))
|
||||
print(df_stable.to_markdown(index=False))
|
||||
|
||||
print('\n## Incubating Falco Rules\n')
|
||||
|
|
|
@ -0,0 +1,166 @@
|
|||
version = 1
|
||||
revision = 1
|
||||
requires-python = ">=3.12"
|
||||
|
||||
[[package]]
|
||||
name = "numpy"
|
||||
version = "2.2.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/fb/90/8956572f5c4ae52201fdec7ba2044b2c882832dcec7d5d0922c9e9acf2de/numpy-2.2.3.tar.gz", hash = "sha256:dbdc15f0c81611925f382dfa97b3bd0bc2c1ce19d4fe50482cb0ddc12ba30020", size = 20262700 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/43/ec/43628dcf98466e087812142eec6d1c1a6c6bdfdad30a0aa07b872dc01f6f/numpy-2.2.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12c045f43b1d2915eca6b880a7f4a256f59d62df4f044788c8ba67709412128d", size = 20929458 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9b/c0/2f4225073e99a5c12350954949ed19b5d4a738f541d33e6f7439e33e98e4/numpy-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:87eed225fd415bbae787f93a457af7f5990b92a334e346f72070bf569b9c9c95", size = 14115299 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ca/fa/d2c5575d9c734a7376cc1592fae50257ec95d061b27ee3dbdb0b3b551eb2/numpy-2.2.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:712a64103d97c404e87d4d7c47fb0c7ff9acccc625ca2002848e0d53288b90ea", size = 5145723 },
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/dc/023dad5b268a7895e58e791f28dc1c60eb7b6c06fcbc2af8538ad069d5f3/numpy-2.2.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:a5ae282abe60a2db0fd407072aff4599c279bcd6e9a2475500fc35b00a57c532", size = 6678797 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3f/19/bcd641ccf19ac25abb6fb1dcd7744840c11f9d62519d7057b6ab2096eb60/numpy-2.2.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5266de33d4c3420973cf9ae3b98b54a2a6d53a559310e3236c4b2b06b9c07d4e", size = 14067362 },
|
||||
{ url = "https://files.pythonhosted.org/packages/39/04/78d2e7402fb479d893953fb78fa7045f7deb635ec095b6b4f0260223091a/numpy-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b787adbf04b0db1967798dba8da1af07e387908ed1553a0d6e74c084d1ceafe", size = 16116679 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d0/a1/e90f7aa66512be3150cb9d27f3d9995db330ad1b2046474a13b7040dfd92/numpy-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:34c1b7e83f94f3b564b35f480f5652a47007dd91f7c839f404d03279cc8dd021", size = 15264272 },
|
||||
{ url = "https://files.pythonhosted.org/packages/dc/b6/50bd027cca494de4fa1fc7bf1662983d0ba5f256fa0ece2c376b5eb9b3f0/numpy-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4d8335b5f1b6e2bce120d55fb17064b0262ff29b459e8493d1785c18ae2553b8", size = 17880549 },
|
||||
{ url = "https://files.pythonhosted.org/packages/96/30/f7bf4acb5f8db10a96f73896bdeed7a63373137b131ca18bd3dab889db3b/numpy-2.2.3-cp312-cp312-win32.whl", hash = "sha256:4d9828d25fb246bedd31e04c9e75714a4087211ac348cb39c8c5f99dbb6683fe", size = 6293394 },
|
||||
{ url = "https://files.pythonhosted.org/packages/42/6e/55580a538116d16ae7c9aa17d4edd56e83f42126cb1dfe7a684da7925d2c/numpy-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:83807d445817326b4bcdaaaf8e8e9f1753da04341eceec705c001ff342002e5d", size = 12626357 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0e/8b/88b98ed534d6a03ba8cddb316950fe80842885709b58501233c29dfa24a9/numpy-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7bfdb06b395385ea9b91bf55c1adf1b297c9fdb531552845ff1d3ea6e40d5aba", size = 20916001 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/b4/def6ec32c725cc5fbd8bdf8af80f616acf075fe752d8a23e895da8c67b70/numpy-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:23c9f4edbf4c065fddb10a4f6e8b6a244342d95966a48820c614891e5059bb50", size = 14130721 },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/60/70af0acc86495b25b672d403e12cb25448d79a2b9658f4fc45e845c397a8/numpy-2.2.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:a0c03b6be48aaf92525cccf393265e02773be8fd9551a2f9adbe7db1fa2b60f1", size = 5130999 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2e/69/d96c006fb73c9a47bcb3611417cf178049aae159afae47c48bd66df9c536/numpy-2.2.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:2376e317111daa0a6739e50f7ee2a6353f768489102308b0d98fcf4a04f7f3b5", size = 6665299 },
|
||||
{ url = "https://files.pythonhosted.org/packages/5a/3f/d8a877b6e48103733ac224ffa26b30887dc9944ff95dffdfa6c4ce3d7df3/numpy-2.2.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8fb62fe3d206d72fe1cfe31c4a1106ad2b136fcc1606093aeab314f02930fdf2", size = 14064096 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/43/619c2c7a0665aafc80efca465ddb1f260287266bdbdce517396f2f145d49/numpy-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:52659ad2534427dffcc36aac76bebdd02b67e3b7a619ac67543bc9bfe6b7cdb1", size = 16114758 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d9/79/ee4fe4f60967ccd3897aa71ae14cdee9e3c097e3256975cc9575d393cb42/numpy-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:1b416af7d0ed3271cad0f0a0d0bee0911ed7eba23e66f8424d9f3dfcdcae1304", size = 15259880 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/c8/8b55cf05db6d85b7a7d414b3d1bd5a740706df00bfa0824a08bf041e52ee/numpy-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:1402da8e0f435991983d0a9708b779f95a8c98c6b18a171b9f1be09005e64d9d", size = 17876721 },
|
||||
{ url = "https://files.pythonhosted.org/packages/21/d6/b4c2f0564b7dcc413117b0ffbb818d837e4b29996b9234e38b2025ed24e7/numpy-2.2.3-cp313-cp313-win32.whl", hash = "sha256:136553f123ee2951bfcfbc264acd34a2fc2f29d7cdf610ce7daf672b6fbaa693", size = 6290195 },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/e7/7d55a86719d0de7a6a597949f3febefb1009435b79ba510ff32f05a8c1d7/numpy-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:5b732c8beef1d7bc2d9e476dbba20aaff6167bf205ad9aa8d30913859e82884b", size = 12619013 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a6/1f/0b863d5528b9048fd486a56e0b97c18bf705e88736c8cea7239012119a54/numpy-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:435e7a933b9fda8126130b046975a968cc2d833b505475e588339e09f7672890", size = 20944621 },
|
||||
{ url = "https://files.pythonhosted.org/packages/aa/99/b478c384f7a0a2e0736177aafc97dc9152fc036a3fdb13f5a3ab225f1494/numpy-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7678556eeb0152cbd1522b684dcd215250885993dd00adb93679ec3c0e6e091c", size = 14142502 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fb/61/2d9a694a0f9cd0a839501d362de2a18de75e3004576a3008e56bdd60fcdb/numpy-2.2.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:2e8da03bd561504d9b20e7a12340870dfc206c64ea59b4cfee9fceb95070ee94", size = 5176293 },
|
||||
{ url = "https://files.pythonhosted.org/packages/33/35/51e94011b23e753fa33f891f601e5c1c9a3d515448659b06df9d40c0aa6e/numpy-2.2.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:c9aa4496fd0e17e3843399f533d62857cef5900facf93e735ef65aa4bbc90ef0", size = 6691874 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ff/cf/06e37619aad98a9d03bd8d65b8e3041c3a639be0f5f6b0a0e2da544538d4/numpy-2.2.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f4ca91d61a4bf61b0f2228f24bbfa6a9facd5f8af03759fe2a655c50ae2c6610", size = 14036826 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/93/5d7d19955abd4d6099ef4a8ee006f9ce258166c38af259f9e5558a172e3e/numpy-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:deaa09cd492e24fd9b15296844c0ad1b3c976da7907e1c1ed3a0ad21dded6f76", size = 16096567 },
|
||||
{ url = "https://files.pythonhosted.org/packages/af/53/d1c599acf7732d81f46a93621dab6aa8daad914b502a7a115b3f17288ab2/numpy-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:246535e2f7496b7ac85deffe932896a3577be7af8fb7eebe7146444680297e9a", size = 15242514 },
|
||||
{ url = "https://files.pythonhosted.org/packages/53/43/c0f5411c7b3ea90adf341d05ace762dad8cb9819ef26093e27b15dd121ac/numpy-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:daf43a3d1ea699402c5a850e5313680ac355b4adc9770cd5cfc2940e7861f1bf", size = 17872920 },
|
||||
{ url = "https://files.pythonhosted.org/packages/5b/57/6dbdd45ab277aff62021cafa1e15f9644a52f5b5fc840bc7591b4079fb58/numpy-2.2.3-cp313-cp313t-win32.whl", hash = "sha256:cf802eef1f0134afb81fef94020351be4fe1d6681aadf9c5e862af6602af64ef", size = 6346584 },
|
||||
{ url = "https://files.pythonhosted.org/packages/97/9b/484f7d04b537d0a1202a5ba81c6f53f1846ae6c63c2127f8df869ed31342/numpy-2.2.3-cp313-cp313t-win_amd64.whl", hash = "sha256:aee2512827ceb6d7f517c8b85aa5d3923afe8fc7a57d028cffcd522f1c6fd082", size = 12706784 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pandas"
|
||||
version = "2.2.3"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "numpy" },
|
||||
{ name = "python-dateutil" },
|
||||
{ name = "pytz" },
|
||||
{ name = "tzdata" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/9c/d6/9f8431bacc2e19dca897724cd097b1bb224a6ad5433784a44b587c7c13af/pandas-2.2.3.tar.gz", hash = "sha256:4f18ba62b61d7e192368b84517265a99b4d7ee8912f8708660fb4a366cc82667", size = 4399213 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/17/a3/fb2734118db0af37ea7433f57f722c0a56687e14b14690edff0cdb4b7e58/pandas-2.2.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b1d432e8d08679a40e2a6d8b2f9770a5c21793a6f9f47fdd52c5ce1948a5a8a9", size = 12529893 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e1/0c/ad295fd74bfac85358fd579e271cded3ac969de81f62dd0142c426b9da91/pandas-2.2.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a5a1595fe639f5988ba6a8e5bc9649af3baf26df3998a0abe56c02609392e0a4", size = 11363475 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c6/2a/4bba3f03f7d07207481fed47f5b35f556c7441acddc368ec43d6643c5777/pandas-2.2.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:5de54125a92bb4d1c051c0659e6fcb75256bf799a732a87184e5ea503965bce3", size = 15188645 },
|
||||
{ url = "https://files.pythonhosted.org/packages/38/f8/d8fddee9ed0d0c0f4a2132c1dfcf0e3e53265055da8df952a53e7eaf178c/pandas-2.2.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fffb8ae78d8af97f849404f21411c95062db1496aeb3e56f146f0355c9989319", size = 12739445 },
|
||||
{ url = "https://files.pythonhosted.org/packages/20/e8/45a05d9c39d2cea61ab175dbe6a2de1d05b679e8de2011da4ee190d7e748/pandas-2.2.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:6dfcb5ee8d4d50c06a51c2fffa6cff6272098ad6540aed1a76d15fb9318194d8", size = 16359235 },
|
||||
{ url = "https://files.pythonhosted.org/packages/1d/99/617d07a6a5e429ff90c90da64d428516605a1ec7d7bea494235e1c3882de/pandas-2.2.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:062309c1b9ea12a50e8ce661145c6aab431b1e99530d3cd60640e255778bd43a", size = 14056756 },
|
||||
{ url = "https://files.pythonhosted.org/packages/29/d4/1244ab8edf173a10fd601f7e13b9566c1b525c4f365d6bee918e68381889/pandas-2.2.3-cp312-cp312-win_amd64.whl", hash = "sha256:59ef3764d0fe818125a5097d2ae867ca3fa64df032331b7e0917cf5d7bf66b13", size = 11504248 },
|
||||
{ url = "https://files.pythonhosted.org/packages/64/22/3b8f4e0ed70644e85cfdcd57454686b9057c6c38d2f74fe4b8bc2527214a/pandas-2.2.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f00d1345d84d8c86a63e476bb4955e46458b304b9575dcf71102b5c705320015", size = 12477643 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e4/93/b3f5d1838500e22c8d793625da672f3eec046b1a99257666c94446969282/pandas-2.2.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3508d914817e153ad359d7e069d752cdd736a247c322d932eb89e6bc84217f28", size = 11281573 },
|
||||
{ url = "https://files.pythonhosted.org/packages/f5/94/6c79b07f0e5aab1dcfa35a75f4817f5c4f677931d4234afcd75f0e6a66ca/pandas-2.2.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:22a9d949bfc9a502d320aa04e5d02feab689d61da4e7764b62c30b991c42c5f0", size = 15196085 },
|
||||
{ url = "https://files.pythonhosted.org/packages/e8/31/aa8da88ca0eadbabd0a639788a6da13bb2ff6edbbb9f29aa786450a30a91/pandas-2.2.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f3a255b2c19987fbbe62a9dfd6cff7ff2aa9ccab3fc75218fd4b7530f01efa24", size = 12711809 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ee/7c/c6dbdb0cb2a4344cacfb8de1c5808ca885b2e4dcfde8008266608f9372af/pandas-2.2.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:800250ecdadb6d9c78eae4990da62743b857b470883fa27f652db8bdde7f6659", size = 16356316 },
|
||||
{ url = "https://files.pythonhosted.org/packages/57/b7/8b757e7d92023b832869fa8881a992696a0bfe2e26f72c9ae9f255988d42/pandas-2.2.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6374c452ff3ec675a8f46fd9ab25c4ad0ba590b71cf0656f8b6daa5202bca3fb", size = 14022055 },
|
||||
{ url = "https://files.pythonhosted.org/packages/3b/bc/4b18e2b8c002572c5a441a64826252ce5da2aa738855747247a971988043/pandas-2.2.3-cp313-cp313-win_amd64.whl", hash = "sha256:61c5ad4043f791b61dd4752191d9f07f0ae412515d59ba8f005832a532f8736d", size = 11481175 },
|
||||
{ url = "https://files.pythonhosted.org/packages/76/a3/a5d88146815e972d40d19247b2c162e88213ef51c7c25993942c39dbf41d/pandas-2.2.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:3b71f27954685ee685317063bf13c7709a7ba74fc996b84fc6821c59b0f06468", size = 12615650 },
|
||||
{ url = "https://files.pythonhosted.org/packages/9c/8c/f0fd18f6140ddafc0c24122c8a964e48294acc579d47def376fef12bcb4a/pandas-2.2.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:38cf8125c40dae9d5acc10fa66af8ea6fdf760b2714ee482ca691fc66e6fcb18", size = 11290177 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ed/f9/e995754eab9c0f14c6777401f7eece0943840b7a9fc932221c19d1abee9f/pandas-2.2.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ba96630bc17c875161df3818780af30e43be9b166ce51c9a18c1feae342906c2", size = 14651526 },
|
||||
{ url = "https://files.pythonhosted.org/packages/25/b0/98d6ae2e1abac4f35230aa756005e8654649d305df9a28b16b9ae4353bff/pandas-2.2.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1db71525a1538b30142094edb9adc10be3f3e176748cd7acc2240c2f2e5aa3a4", size = 11871013 },
|
||||
{ url = "https://files.pythonhosted.org/packages/cc/57/0f72a10f9db6a4628744c8e8f0df4e6e21de01212c7c981d31e50ffc8328/pandas-2.2.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:15c0e1e02e93116177d29ff83e8b1619c93ddc9c49083f237d4312337a61165d", size = 15711620 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ab/5f/b38085618b950b79d2d9164a711c52b10aefc0ae6833b96f626b7021b2ed/pandas-2.2.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ad5b65698ab28ed8d7f18790a0dc58005c7629f227be9ecc1072aa74c0c1d43a", size = 13098436 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "python-dateutil"
|
||||
version = "2.9.0.post0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
dependencies = [
|
||||
{ name = "six" },
|
||||
]
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytz"
|
||||
version = "2025.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/5f/57/df1c9157c8d5a05117e455d66fd7cf6dbc46974f832b1058ed4856785d8a/pytz-2025.1.tar.gz", hash = "sha256:c2db42be2a2518b28e65f9207c4d05e6ff547d1efa4086469ef855e4ab70178e", size = 319617 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/eb/38/ac33370d784287baa1c3d538978b5e2ea064d4c1b93ffbd12826c190dd10/pytz-2025.1-py2.py3-none-any.whl", hash = "sha256:89dd22dca55b46eac6eda23b2d72721bf1bdfef212645d81513ef5d03038de57", size = 507930 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "6.0.2"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154 },
|
||||
{ url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223 },
|
||||
{ url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542 },
|
||||
{ url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164 },
|
||||
{ url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611 },
|
||||
{ url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591 },
|
||||
{ url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338 },
|
||||
{ url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309 },
|
||||
{ url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679 },
|
||||
{ url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428 },
|
||||
{ url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361 },
|
||||
{ url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523 },
|
||||
{ url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597 },
|
||||
{ url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527 },
|
||||
{ url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scripts"
|
||||
version = "0.1.0"
|
||||
source = { virtual = "." }
|
||||
dependencies = [
|
||||
{ name = "pandas" },
|
||||
{ name = "pyyaml" },
|
||||
{ name = "tabulate" },
|
||||
]
|
||||
|
||||
[package.metadata]
|
||||
requires-dist = [
|
||||
{ name = "pandas", specifier = ">=2.2.3" },
|
||||
{ name = "pyyaml", specifier = ">=6.0.2" },
|
||||
{ name = "tabulate", specifier = ">=0.9.0" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
version = "1.17.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tabulate"
|
||||
version = "0.9.0"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/ec/fe/802052aecb21e3797b8f7902564ab6ea0d60ff8ca23952079064155d1ae1/tabulate-0.9.0.tar.gz", hash = "sha256:0095b12bf5966de529c0feb1fa08671671b3368eec77d7ef7ab114be2c068b3c", size = 81090 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/40/44/4a5f08c96eb108af5cb50b41f76142f0afa346dfa99d5296fe7202a11854/tabulate-0.9.0-py3-none-any.whl", hash = "sha256:024ca478df22e9340661486f85298cff5f6dcdba14f3813e8830015b9ed1948f", size = 35252 },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tzdata"
|
||||
version = "2025.1"
|
||||
source = { registry = "https://pypi.org/simple" }
|
||||
sdist = { url = "https://files.pythonhosted.org/packages/43/0f/fa4723f22942480be4ca9527bbde8d43f6c3f2fe8412f00e7f5f6746bc8b/tzdata-2025.1.tar.gz", hash = "sha256:24894909e88cdb28bd1636c6887801df64cb485bd593f2fd83ef29075a81d694", size = 194950 }
|
||||
wheels = [
|
||||
{ url = "https://files.pythonhosted.org/packages/0f/dd/84f10e23edd882c6f968c21c2434fe67bd4a528967067515feca9e611e5e/tzdata-2025.1-py2.py3-none-any.whl", hash = "sha256:7e127113816800496f027041c570f50bcd464a020098a3b6b199517772303639", size = 346762 },
|
||||
]
|
|
@ -0,0 +1,6 @@
|
|||
extends: default
|
||||
|
||||
rules:
|
||||
line-length:
|
||||
max: 130
|
||||
level: error
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
if: github.event.workflow_run.event == 'pull_request'
|
||||
steps:
|
||||
- name: 'Download artifact'
|
||||
uses: actions/github-script@v6.4.1
|
||||
uses: actions/github-script@v7.0.1
|
||||
with:
|
||||
script: |
|
||||
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
|
||||
|
@ -39,7 +39,7 @@ jobs:
|
|||
run: unzip pr.zip
|
||||
|
||||
- name: 'Comment on PR'
|
||||
uses: actions/github-script@v6.4.1
|
||||
uses: actions/github-script@v7.0.1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
|
|
|
@ -2,7 +2,7 @@ name: Deploy Github Pages
|
|||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
|
@ -19,29 +19,25 @@ jobs:
|
|||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- uses: actions/setup-python@v2
|
||||
with:
|
||||
python-version: 3.x
|
||||
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v5
|
||||
|
||||
- name: Generate updated inventory
|
||||
run: |
|
||||
mkdir docs/
|
||||
pip install -r .github/scripts/requirements.txt
|
||||
python .github/scripts/rules_overview_generator.py --rules_dir=rules > docs/index.md
|
||||
|
||||
cd .github/scripts/
|
||||
uv run rules_overview_generator.py --rules_dir=../../rules > ../../docs/index.md
|
||||
|
||||
- name: Disable Table Of Content for overview
|
||||
run: |
|
||||
sed -i '1s/^/---\nhide:\n- toc\n---\n\n/' docs/index.md
|
||||
|
||||
- run: pip install mkdocs mkdocs-material
|
||||
- run: uvx --with mkdocs-material mkdocs build
|
||||
|
||||
- run: mkdocs build
|
||||
|
||||
- uses: actions/upload-pages-artifact@v1
|
||||
- uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3
|
||||
with:
|
||||
path: 'site'
|
||||
|
||||
- id: deployment
|
||||
uses: actions/deploy-pages@v1
|
||||
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4
|
||||
|
|
|
@ -11,10 +11,10 @@ jobs:
|
|||
|
||||
steps:
|
||||
- name: Checkout Rules
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '^1.19'
|
||||
|
||||
|
|
|
@ -27,11 +27,11 @@ jobs:
|
|||
|
||||
# Get rules repository
|
||||
- name: Checkout Rules
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Get registry artifact tool
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version-file: build/registry/go.mod
|
||||
|
||||
|
@ -58,9 +58,7 @@ jobs:
|
|||
|
||||
# Create a signature of the rules artifact as OCI artifact
|
||||
- name: Install Cosign
|
||||
uses: sigstore/cosign-installer@v3.1.0
|
||||
with:
|
||||
cosign-release: 'v2.1.0'
|
||||
uses: sigstore/cosign-installer@v3.9.0
|
||||
|
||||
- name: Login with cosign
|
||||
run: cosign login $OCI_REGISTRY --username ${{ github.repository_owner }} --password ${{ secrets.GITHUB_TOKEN }}
|
||||
|
@ -69,7 +67,7 @@ jobs:
|
|||
run: cosign sign --yes ${{ steps.oci_build.outputs.ARTIFACT_REPO_DIGEST }}
|
||||
|
||||
- name: Configure AWS credentials
|
||||
uses: aws-actions/configure-aws-credentials@v1
|
||||
uses: aws-actions/configure-aws-credentials@v4
|
||||
with:
|
||||
role-to-assume: "arn:aws:iam::292999226676:role/terraform-20230120142903096000000002"
|
||||
aws-region: ${{ env.AWS_S3_REGION }}
|
||||
|
|
|
@ -18,12 +18,12 @@ jobs:
|
|||
falco-versions: ${{ steps.set-falco-versions.outputs.versions }}
|
||||
steps:
|
||||
- name: Checkout rules
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Get changed files
|
||||
id: changed-files
|
||||
if: github.event_name == 'pull_request'
|
||||
uses: Ana06/get-changed-files@v2.2.0
|
||||
uses: Ana06/get-changed-files@v2.3.0
|
||||
with:
|
||||
format: space-delimited
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
@ -31,15 +31,17 @@ jobs:
|
|||
- name: Find changed rules files
|
||||
id: set-changed-files
|
||||
run: |
|
||||
# if we skip changed-files because we're not in a pull-request,
|
||||
# then we consider all the rules contained in the repo
|
||||
# Find any changed file located under the /rules folder that matches the naming convention <ruleset>_rules.yaml.
|
||||
# See https://github.com/falcosecurity/rules/blob/main/README.md#naming-convention for details.
|
||||
# Additionally, if we skip changed-files because we're not in a pull request,
|
||||
# then we consider all the rules contained in the repository.
|
||||
all_files="${{ steps.changed-files.outputs.all }}"
|
||||
values=""
|
||||
if [ -z "$all_files" ]; then
|
||||
values=$(ls rules/*.yaml)
|
||||
values=$(ls rules/*_rules.yaml)
|
||||
else
|
||||
for changed_file in $all_files; do
|
||||
if [[ "${changed_file}" =~ ^rules/.* ]]; then
|
||||
if [[ "${changed_file}" =~ ^rules/[^/]*_rules\.yaml$ ]]; then
|
||||
values=${values}${changed_file}$'\n'
|
||||
fi
|
||||
done
|
||||
|
@ -67,12 +69,12 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.19.0"
|
||||
|
||||
- name: Checkout rules
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Build checker tool
|
||||
working-directory: build/checker
|
||||
|
@ -86,7 +88,7 @@ jobs:
|
|||
run: |
|
||||
build/checker/rules-check \
|
||||
validate \
|
||||
--falco-image="falcosecurity/falco-no-driver:${{ matrix.falco-version }}" \
|
||||
--falco-image="falcosecurity/falco:${{ matrix.falco-version }}" \
|
||||
-r ${{ matrix.rules-file }}
|
||||
|
||||
check-version:
|
||||
|
@ -102,18 +104,18 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Setup Golang
|
||||
uses: actions/setup-go@v3
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: "1.19.0"
|
||||
|
||||
- name: Checkout rules
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Get all git tags
|
||||
run: git fetch --tags origin
|
||||
|
||||
- name: Get changed files
|
||||
uses: Ana06/get-changed-files@v2.2.0
|
||||
uses: Ana06/get-changed-files@v2.3.0
|
||||
id: changed
|
||||
with:
|
||||
format: space-delimited
|
||||
|
@ -134,7 +136,7 @@ jobs:
|
|||
"${{ matrix.rules-file }}" \
|
||||
result.txt \
|
||||
build/checker/rules-check \
|
||||
"falcosecurity/falco-no-driver:$FALCO_VERSION"
|
||||
"falcosecurity/falco:$FALCO_VERSION"
|
||||
if [ -s result.txt ]; then
|
||||
echo "comment_file=result.txt" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
@ -146,7 +148,7 @@ jobs:
|
|||
cp ${{ steps.compare.outputs.comment_file }} ./pr/COMMENT-${{ strategy.job-index }}
|
||||
|
||||
- name: Upload PR info as artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
if: steps.compare.outputs.comment_file != ''
|
||||
with:
|
||||
name: pr-${{ strategy.job-index }}
|
||||
|
@ -159,7 +161,7 @@ jobs:
|
|||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Download PR infos
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: tmp-artifacts
|
||||
|
||||
|
@ -185,7 +187,7 @@ jobs:
|
|||
echo ""
|
||||
|
||||
- name: Upload PR info as artifact
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: pr
|
||||
path: pr/
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
name: Yamllint Github Actions
|
||||
on:
|
||||
pull_request:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
lintFalcoRules:
|
||||
name: Yamllint
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repo
|
||||
uses: actions/checkout@v4
|
||||
- name: yaml-lint
|
||||
uses: ibiqlik/action-yamllint@v3
|
||||
with:
|
||||
file_or_dir: rules/*.yaml
|
||||
env:
|
||||
YAMLLINT_CONFIG_FILE: .github/workflows/.yamllint
|
|
@ -0,0 +1,196 @@
|
|||
# Specific project files
|
||||
build/mitre_attack_checker/build
|
||||
build/mitre_attack_checker/reports
|
||||
**/falco_rules_mitre_errors.json
|
||||
**/application_rules_errors.json
|
||||
|
||||
# IntelliJ project files
|
||||
.idea
|
||||
*.iml
|
||||
out
|
||||
gen
|
||||
### Go template
|
||||
# If you prefer the allow list template instead of the deny list, see community template:
|
||||
# https://github.com/github/gitignore/blob/main/community/Golang/Go.AllowList.gitignore
|
||||
#
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Test binary, built with `go test -c`
|
||||
*.test
|
||||
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# Dependency directories (remove the comment below to include it)
|
||||
# vendor/
|
||||
|
||||
# Go workspace file
|
||||
go.work
|
||||
|
||||
### Python template
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
cover/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
.pybuilder/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
# For a library or package, you might want to ignore these files since the code is
|
||||
# intended to run in multiple environments; otherwise, check them in:
|
||||
# .python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# poetry
|
||||
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
||||
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
||||
# commonly ignored for libraries.
|
||||
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
||||
#poetry.lock
|
||||
|
||||
# pdm
|
||||
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
||||
#pdm.lock
|
||||
# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
|
||||
# in version control.
|
||||
# https://pdm.fming.dev/#use-with-ide
|
||||
.pdm.toml
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
||||
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython debug symbols
|
||||
cython_debug/
|
||||
|
||||
# PyCharm
|
||||
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
||||
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
||||
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
.idea/
|
||||
.run/
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
Thank you for your interest in contributing to Falco's rules!
|
||||
|
||||
This repo contains a dedicated rules contributing guide that highlights the rules maturity framework definitions as well as the criteria for rules acceptance. This guide inherits from the general [contributing](https://github.com/falcosecurity/.github/blob/main/CONTRIBUTING.md) guide.
|
||||
This repository includes a dedicated guide for contributing rules, outlining the definitions of the rules maturity framework and the criteria for rule acceptance. This guide inherits from the general [contributing](https://github.com/falcosecurity/.github/blob/main/CONTRIBUTING.md) guide.
|
||||
|
||||
All rules must be licensed under the [Apache 2.0 License](./LICENSE).
|
||||
|
||||
|
@ -15,9 +15,9 @@ All rules must be licensed under the [Apache 2.0 License](./LICENSE).
|
|||
|
||||
# Rules Maturity Framework
|
||||
|
||||
The rules maturity framework was introduced based on this [proposal](proposals/20230605-rules-adoption-management-maturity-framework.md).
|
||||
The rules maturity framework was established following this [proposal](proposals/20230605-rules-adoption-management-maturity-framework.md).
|
||||
|
||||
At a high level, the Falco project maintains community-contributed syscall and container event-based [rules](https://github.com/falcosecurity/rules/blob/main/rules/), with `maturity_stable` tagged rules being included in the default Falco package. Rules at the remaining maturity levels may need extra customization to ensure effective adoption. Consequently, certain rules are intentionally disabled by default, irrespective of their maturity level.
|
||||
At a high level, The Falco Project maintains community-contributed syscall and container event-based [rules](https://github.com/falcosecurity/rules/blob/main/rules/), with `maturity_stable` tagged rules being included in the Falco release package. Other maturity-level rules are released separately, requiring explicit installation and possible customization for effective. In essence, there are now dedicated rule files for each maturity level.
|
||||
|
||||
The next sections will dive deeper into how the framework works and offer guidance on selecting a maturity level for specific rules.
|
||||
|
||||
|
@ -27,7 +27,7 @@ As specified in the tags section of the [Style Guide of Falco Rules](https://fal
|
|||
|
||||
A new rule typically starts as `maturity_sandbox` and, in some cases, as `maturity_incubating`. However, it cannot immediately be at the `maturity_stable` level.
|
||||
|
||||
Only rules at the `maturity_stable` level are distributed with the Falco package by default and live in the established `falco_rules.yaml` file. All other rules at the remaining maturity levels can be found in the Falco rules file according to their level. These rules can be used by adopters if they choose to do so. They are made available to the adopter through the same means as the `falco_rules.yaml` file, either by directly retrieving them from this repository or by fetching them via `falcoctl`. Adopters have the flexibility to choose how they want to tailor the upstream rules to their needs.
|
||||
Only rules at the `maturity_stable` level are distributed with the Falco release package and live in the established `falco_rules.yaml` file. All rules at the remaining maturity levels can be found in the Falco rules file according to their respective levels, and they need to be installed separately. They are made available to the adopter through the same means as the `falco_rules.yaml` file, either by directly retrieving them from this repository or by fetching them via `falcoctl`. Adopters have the flexibility to choose how they install and customize the upstream rules to suit their needs.
|
||||
|
||||
Rules files:
|
||||
|
||||
|
@ -52,7 +52,7 @@ The levels:
|
|||
- **maturity_sandbox** indicates that the rule is in an experimental stage. The potential for broader usefulness and relevance of "sandbox" rules is currently being assessed. These rules can serve as inspiration and adhere to the minimum acceptance criteria for rules.
|
||||
- **maturity_deprecated** indicates that, upon re-assessment, the rule was deemed less applicable to the broader community. Each adopter needs to determine the relevance of these rules on their own. They are kept as examples but are no longer actively supported or tuned by The Falco Project.
|
||||
|
||||
The rules maturity tag reflects the robustness, relevance, applicability, and stability of each predefined rule in the [falcosecurity/rules](https://github.com/falcosecurity/rules/blob/main/rules/) repository. It serves as general guidance to determine which rules may provide the highest return on investment.
|
||||
In summary, the rules maturity tag reflects the robustness, relevance, applicability, and stability of each predefined rule in the [falcosecurity/rules](https://github.com/falcosecurity/rules/blob/main/rules/) repository. It serves as general guidance to determine which rules may provide the highest return on investment.
|
||||
|
||||
## Justification of Rules Maturity Framework for Falco Adoption
|
||||
|
||||
|
@ -61,19 +61,21 @@ Additionally, due to this framework, adopters should find themselves with a clea
|
|||
|
||||
The rules maturity framework aligns with the [status](https://github.com/falcosecurity/evolution/blob/main/REPOSITORIES.md#status) levels used within The Falco Project repositories, namely "Stable", "Incubating", "Sandbox" and "Deprecated".
|
||||
|
||||
Not every rule has the potential to evolve and reach the "stable" level. This is because "stable" rules should address a broader category of attacks rather than being overly specific and easily bypassed. However, this does not mean that very specific rules do not provide value; on the contrary, they can serve a very specific purpose. The intention of the new framework is to make it clearer for adopters to recognize that they need to evaluate such rules for their own environment.
|
||||
Not every rule has the potential to evolve and reach the "stable" level. This is because "stable" rules should address a broader range of attacks rather than being overly specific—such as detecting a single narrow CVE for a less common type of application, which could be easily bypassed. However, this does not mean that very specific rules do not provide value; on the contrary, they can serve a very specific purpose. These more specific rules may be better suited for custom adoption rather than integration into the upstream Falco rules.
|
||||
|
||||
The new framework aims to help adopters easily identify the nature of a rule, whether it's more behavioral or signature-based. This is accomplished by providing clearer descriptions. You can explore this in more detail in the [Rules Overview Document](https://falcosecurity.github.io/rules/).
|
||||
|
||||
The maturity level of the rules, however, does not directly reflect their potential for generating noise in the adopters' environment. This is due to the unique and constantly changing nature of each environment, especially in cloud environments, making it challenging to accurately predict the impact of rules.
|
||||
|
||||
Newcomers to Falco will be encouraged to start by configuring their setup with introductory rules labeled as "Falco's default rules" (`maturity_stable`). These rules, which are currently based on syscall and container events, will live in the established [falco_rules.yaml](https://github.com/falcosecurity/rules/blob/main/rules/falco_rules.yaml) file.
|
||||
Newcomers to Falco are encouraged to start by configuring their setup with introductory rules labeled as `maturity_stable`. These rules, which are currently based on syscall and container events live in the established [falco_rules.yaml](https://github.com/falcosecurity/rules/blob/main/rules/falco_rules.yaml) file.
|
||||
|
||||
As users become more familiar with Falco and better understand their unique environments, they can gradually fine-tune the rules to meet their specific requirements. Tuning rules goes hand in hand with assessing the performance overhead and adjusting Falco's [configuration](https://github.com/falcosecurity/falco/blob/master/falco.yaml) accordingly. This consideration is important to keep in mind as there are usually limitations to the budget allocated for security monitoring.
|
||||
As users become more familiar with Falco and better understand their unique environment, they can gradually fine-tune the rules to meet their specific requirements. Tuning rules goes hand in hand with assessing the performance overhead and adjusting Falco's [configuration](https://github.com/falcosecurity/falco/blob/master/falco.yaml) accordingly. This consideration is important to keep in mind as there are usually limitations to the budget allocated for security monitoring.
|
||||
|
||||
Once adopters have integrated the stable default rules with low False Positives and acceptable performance overhead consistently, they can add a next set of rules. This set may include rules with `maturity_incubating` or `maturity_sandbox`, offering more specific detections and/or broader monitoring, depending on the rule.
|
||||
|
||||
# Rules Acceptance Criteria
|
||||
|
||||
The [maintainers](OWNERS) of this repository reserve the right to make case-by-case decisions regarding rules acceptance and initial maturity leveling.
|
||||
The [maintainers](OWNERS) of this repository kindly reserve the right to make case-by-case decisions regarding rules acceptance and initial maturity leveling.
|
||||
|
||||
The high-level principles that guide the review process for contributors and reviewers are as follows:
|
||||
|
||||
|
@ -81,7 +83,7 @@ The high-level principles that guide the review process for contributors and rev
|
|||
- Each rule conforms to the [Style Guide of Falco Rules](https://falco.org/docs/rules/style-guide/).
|
||||
- In particular, the [Rules Maturity Framework](#rules-maturity-framework) is honored.
|
||||
|
||||
> Note: Any rule that would require using the `-A` flag (enabling high-volume syscalls) cannot be accepted beyond `maturity_sandbox` due to performance impact reasons.
|
||||
> Note: Any rule that would require using the `-A` flag (enabling high-volume syscalls) cannot be accepted beyond `maturity_sandbox` and `enabled: false` due to performance impact reasons. At the moment, we discourage upstream rules based on high-volume syscalls. However, this assessment may change as Falco evolves.
|
||||
|
||||
*Correctness*
|
||||
|
||||
|
@ -89,11 +91,11 @@ As part of the review process, the following aspects will be thoroughly checked
|
|||
|
||||
- Correctness of the expression language, both syntactically and grammatically.
|
||||
- Consistency with the name/description.
|
||||
- If any tests are present, they must pass. During the initial review process and subsequent changes, manual testing should also be conducted to verify that the rule is capable of detecting the cyber threat(s) it aims to detect. In some cases, more realistic testing will be necessary, such as deploying tests to production servers or, at the very least, QA servers.
|
||||
- If any tests are present, they must pass. During the initial review process and subsequent changes, manual testing should also be conducted to verify that the rule is capable of detecting the cyber threat(s) it aims to detect. In some cases, conducting more realistic tests, like deploying the rules on actual servers before acceptance, will be necessary.
|
||||
|
||||
*Robustness*
|
||||
|
||||
To enhance the effectiveness of detection, priority is given to behavioral detections, as opposed to string matching on process command arguments or other fields. This preference is based on the ease with which the latter can be circumvented. The same principle applies when selecting the most robust system call for detecting a specific threat. However, there is a place and purpose for more signature-based detections. The existing rules tagged with `maturity_stable` serve as a good starting point to explore a variety of useful rules that cover various attack vectors and employ both signature and behavior-based detection styles.
|
||||
To enhance the effectiveness of detection, priority is given to behavioral detections, as opposed to string matching on process command arguments or other fields. This preference is based on the ease with which the latter can be circumvented. The same principle applies when selecting the most robust system call for detecting a specific threat. However, there is a place and purpose for more signature-based detections. The existing rules tagged with `maturity_stable` serve as a good starting point to explore a variety of useful rules that cover various attack vectors and employ both signature and behavior-based detection styles. Lastly, The Falco Project favors broader rules over narrow ones addressing a single, less common CVE for an application.
|
||||
|
||||
*Relevance*
|
||||
|
||||
|
@ -105,4 +107,3 @@ Here are some aspects that can be discussed during the review process in order t
|
|||
- Emphasize behavior-detection style + profiling over pure signatures (exceptions to this guideline apply).
|
||||
- Evaluate the rule's effectiveness across diverse workloads (e.g. nodes serving web applications, databases, transactional processing, general compute or CI jobs).
|
||||
- Guidance and templates to assist with tuning can be provided given Falco's current capabilities.
|
||||
|
||||
|
|
3
OWNERS
3
OWNERS
|
@ -5,7 +5,7 @@ approvers:
|
|||
- fededp
|
||||
- andreagit97
|
||||
- lucaguerra
|
||||
- incertum
|
||||
- ekoops
|
||||
reviewers:
|
||||
- leodido
|
||||
- kaizhe
|
||||
|
@ -13,3 +13,4 @@ reviewers:
|
|||
- loresuso
|
||||
emeritus_approvers:
|
||||
- kaizhe
|
||||
- incertum
|
||||
|
|
87
README.md
87
README.md
|
@ -1,35 +1,58 @@
|
|||
# Falco Rules
|
||||
|
||||
[](https://github.com/falcosecurity/evolution/blob/main/REPOSITORIES.md#core-scope) [](https://github.com/falcosecurity/evolution/blob/main/REPOSITORIES.md#stable) [](./LICENSE)
|
||||
[](https://github.com/falcosecurity/rules/releases/latest) [](https://github.com/falcosecurity/falco/releases/latest)
|
||||
|
||||
Note: *This repository has been created upon this [proposal](https://github.com/falcosecurity/falco/blob/master/proposals/20221129-artifacts-distribution.md#move-falco-rules-to-their-own-repo).*
|
||||
[](https://falco.org/docs/rules) [](https://falcosecurity.github.io/rules/) [](https://falco.org/docs/rules/style-guide/)
|
||||
|
||||
This repository maintains the default *rules files* officially owned by the Falcosecurity organization as well as the Falco Rules Files Registry.
|
||||
[](https://falco.org/docs/reference/rules/supported-fields/) [](https://github.com/falcosecurity/libs/blob/master/driver/event_table.c)
|
||||
|
||||
[](https://github.com/falcosecurity/evolution/blob/main/REPOSITORIES.md#core-scope) [](https://github.com/falcosecurity/evolution/blob/main/REPOSITORIES.md#stable) [](./LICENSE) [](https://falcosecurity.github.io/rules/)
|
||||
|
||||
This repository has been created upon this [Proposal](https://github.com/falcosecurity/falco/blob/master/proposals/20221129-artifacts-distribution.md#move-falco-rules-to-their-own-repo) and contains the officially managed [Falco Rules](#falco-rules) by The Falco Project, along with the [Falco Rules Files Registry](#falco-rules-files-registry).
|
||||
|
||||
## Falco Rules
|
||||
|
||||
Rules tell [Falco](https://github.com/falcosecurity/falco) what to do. These rules are pre-defined detections for various security threats, abnormal behaviors, and compliance-related monitoring. Adopters can customize these rules to their specific needs or use them as examples. Please refer to the [official documentation](https://falco.org/docs/rules) to better understand the rules' concepts.
|
||||
Rules tell [Falco](https://github.com/falcosecurity/falco) what to do. These rules are pre-defined detections for various security threats, abnormal behaviors, and compliance-related monitoring.
|
||||
|
||||
The `main` branch contains the most up-to-date state of development. All rules files are located under the [rules folder](rules/). Please refer to our [Release Process](./RELEASE.md) to understand how rules are released. Stable rules are released and published only when a new release gets tagged. This means that rules in the `main` branch can become incompatible with the latest stable Falco release if, for example, new output fields are introduced.
|
||||
</br>
|
||||
|
||||
Links:
|
||||
- [Getting Started with Falco Rules - Official Documentation](https://falco.org/docs/rules)
|
||||
- [Rules Overview Document](https://falcosecurity.github.io/rules/)
|
||||
- [Rules Maturity Framework and Adoption](CONTRIBUTING.md#rules-maturity-framework)
|
||||
<p align="left">
|
||||
<img src="docs/images/start.png" alt="Image" width="21" height="21">
|
||||
Explore the <a href="https://falco.org/docs/rules">Official Documentation</a> for a starting point and better understanding of rule concepts. Users can modify the community-contributed Falco rules to fit their needs or use them as examples. In most cases, users also create their own custom rules. Keep in mind that the rules in this repository are related to Falco's primary monitoring functions, specifically for syscalls and container events. Meanwhile, Falco plugin rules are stored within the respective subfolders of the <a href="https://github.com/falcosecurity/plugins">Plugins</a> repository.</p>
|
||||
</div>
|
||||
|
||||
### Default Rules
|
||||
<p align="left">
|
||||
<img src="docs/images/insight.png" alt="Image" width="18" height="24">
|
||||
Because Falco rules, especially Sandbox and Incubating rules, are dynamic, it's crucial to stay updated. As threats and systems evolve, Falco evolves with each release. Therefore, regularly check the <a href="https://falcosecurity.github.io/rules/">Rules Overview Document</a>, Falco's <a href="https://falco.org/docs/reference/rules/supported-fields/">Supported Fields</a>, and Falco's release notes with every new release. It is recommended to consistently use the most recent <a href='https://github.com/falcosecurity/falco/releases/latest'>Falco Release</a> to avoid compatibility issues.</p>
|
||||
</div>
|
||||
|
||||
The [falco_rules.yaml](rules/falco_rules.yaml) file includes community-contributed Falco rules for syscalls and container events. These rules are part of the default Falco release package and are categorized by maturity level as `maturity_stable`, following the [Rules Maturity Framework](CONTRIBUTING.md#rules-maturity-framework). Rules at the remaining maturity levels can be found within the Falco rules file according to their level. Rules at a maturity level lower than `maturity_stable` may need extra customization to ensure [effective adoption](CONTRIBUTING.md#justification-of-rules-maturity-framework-for-falco-adoption).
|
||||
<p align="left">
|
||||
<img src="docs/images/setting.png" alt="Image" width="23" height="23">
|
||||
Important: The Falco Project only guarantees that the most recent rules releases are compatible with the latest Falco release. Discover all rule files in the <a href="rules/">rules/</a> folder. Refer to our <a href="./RELEASE.md">Release Process</a> and <a href="CONTRIBUTING.md#rules-maturity-framework">Rules Maturity Framework</a> for rule categorization, release procedures, and usage guidelines. Published upon tagging a new release, the <i>maturity_stable</i> rules in the <a href="rules/falco_rules.yaml">falco_rules.yaml</a> file are included in the Falco release package. Other maturity-level rules are released separately, requiring explicit installation and possible customization for effective <a href="CONTRIBUTING.md#justification-of-rules-maturity-framework-for-falco-adoption">Adoption</a>.</p>
|
||||
</div>
|
||||
|
||||
For an up-to-date overview table linking to the respective Mitre Attack resources and more, please refer to the [rules overview](https://falcosecurity.github.io/rules/) document. Lastly, you can find Falco plugins rules in the respective [plugins](https://github.com/falcosecurity/plugins) repos' subfolder.
|
||||
<p align="left">
|
||||
<img src="docs/images/announce.png" alt="Image" width="20" height="20">
|
||||
Beginning with rules version 3.0.0, the <i>required_engine_version</i> follows <a href="https://semver.org/">Semantic Versioning</a> and requires Falco version 0.37.0 or higher. Since rules version <a href="#falco-rules-2x">2.0.0</a>, we've modified our rules' shipping and distribution process. With Falco >= 0.37.0, <a href="https://falco.org/docs/rules/overriding/">Selective Rules Overrides</a> aim to further streamline the customization of rules. Since Falco 0.36.0, you can use the <a href="https://github.com/falcosecurity/falco/blob/master/falco.yaml">rule_matching</a> config to resolve issues with rules overlapping, which is caused by the default "first match wins" principle. Starting from Falco 0.35.0, you have precise control over the syscalls that are being monitored, see <a href="https://github.com/falcosecurity/falco/blob/master/falco.yaml">base_syscalls</a>. Lastly, keep in mind that the <a href="CONTRIBUTING.md#rules-maturity-framework">Rules Maturity Framework</a> is a best effort on the part of the community, and ultimately, you have to decide if any rules are useful for your use cases. </p>
|
||||
</div>
|
||||
|
||||
Interested in contributing your custom rules? Visit the [contributing](#contributing) section below and join the Falco community now.
|
||||
<p align="left">
|
||||
<img src="docs/images/cross.png" alt="Image" width="20" height="20">
|
||||
Be cautious: The <i>main</i> branch has the latest development. Before using rules from the <i>main</i> branch, check for compatibility. Changes like new output fields might cause incompatibilities with the latest stable Falco release. The Falco Project recommends using rules only from the release branches. Lastly, we'd like to highlight the importance of regular engineering effort to effectively adopt Falco rules. Considering that each adopter's system and monitoring needs are unique, it's advisable to view the rules as examples.
|
||||
</p>
|
||||
|
||||
<p align="left">
|
||||
<img src="docs/images/arrow.png" alt="Image" width="20" height="20">
|
||||
Debugging: Historically, we've noted that issues often arise either from incorrect configurations or genuine bugs, acknowledging that no software is entirely bug-free. The Falco Project continually updates its <a href="https://falco.org/docs/install-operate/">Install and Operate</a> and <a href="https://falco.org/docs/troubleshooting/">Troubleshooting</a> guides. We kindly suggest reviewing these guides. In the context of Falco rules, missing fields, such as container images, may be anticipated within our imperfection tolerances under certain circumstances. We are committed to addressing and resolving issues within our control.
|
||||
</p>
|
||||
|
||||
</br>
|
||||
|
||||
## Falco Rules Files Registry
|
||||
|
||||
The Falco Rules Files Registry contains metadata and information about rules files distributed by the Falcosecurity organization. The registry serves as an additional method of making the rules files available to the community, complementing the process of retrieving the rules files from this repository.
|
||||
The Falco Rules Files Registry contains metadata and information about rules files distributed by The Falco Project. The registry serves as an additional method of making the rules files available to the community, complementing the process of retrieving the rules files from this repository.
|
||||
|
||||
Note: _Currently, the registry includes only rules for the syscall call data source; for other data sources see the [plugins repository](https://github.com/falcosecurity/plugins)._
|
||||
Note: _Currently, the registry includes only rules for the syscall call data source; for other data sources see the [Plugins](https://github.com/falcosecurity/plugins) repository._
|
||||
|
||||
### Naming Convention
|
||||
|
||||
|
@ -37,7 +60,7 @@ Rule files must be located in the [/rules](rules) folder of this repository and
|
|||
|
||||
The `<ruleset>` portion represents the _ruleset_ name, which must be an alphanumeric string, separated by `-`, entirely in lowercase, and beginning with a letter.
|
||||
|
||||
Rule files are subsequently released using Git tags. The tag name should follow the pattern `<ruleset>-rules-<version>`, where `<version>` adheres to [Semantic Versioning](https://semver.org/). See [RELEASE.md](RELEASE.md) for more details about our release process.
|
||||
Rule files are subsequently released using Git tags. The tag name should follow the pattern `<ruleset>-rules-<version>`, where `<version>` adheres to [Semantic Versioning](https://semver.org/). See [RELEASE](RELEASE.md) document for more details about our release process.
|
||||
|
||||
For instance, the _falco_ ruleset is stored under [/rules/falco_rules.yaml](rules/falco_rules.yaml), and its version _1.0.0_ was released using the [falco-rules-1.0.0](https://github.com/falcosecurity/rules/releases/tag/falco-rules-1.0.0) tag.
|
||||
|
||||
|
@ -79,11 +102,39 @@ Please refer to the automatically generated [rules overview](https://falcosecuri
|
|||
|
||||
-->
|
||||
|
||||
## Falco Rules 2.x
|
||||
|
||||
Since version 2.0.0, the rules distributed from this repository have been split into three parts:
|
||||
|
||||
- [Stable](https://github.com/falcosecurity/rules/blob/main/rules/falco_rules.yaml) Falco rules. Those are the only ones that are bundled in the Falco by default. It is very important to have a set of stable rules vetted by the community. To learn more about the criterias that are required for a rule to become stable, see the [Contributing](https://github.com/falcosecurity/rules/blob/main/CONTRIBUTING.md) guide.
|
||||
- [Incubating](https://github.com/falcosecurity/rules/blob/main/rules/falco-incubating_rules.yaml) rules, which provide a certain level of robustness guarantee but have been identified by experts as catering to more specific use cases, which may or may not be relevant for each adopter.
|
||||
- [Sandbox](https://github.com/falcosecurity/rules/blob/main/rules/falco-sandbox_rules.yaml) rules, which are more experimental.
|
||||
|
||||
Previously, Falco used to bundle all the community rules in its default distribution. Today you can choose which set of rules you want to load in your distribution, depending on your preferred installation method:
|
||||
|
||||
### Helm Chart
|
||||
|
||||
If you are using the official Helm chart, you can add the incubating and/or sandbox repository in your [falcoctl](https://github.com/falcosecurity/charts/blob/f1062000e2e61332b3a8ea892a1765e4f4a60ec6/falco/values.yaml#L406) config and by enabling them in the corresponding `falco.yaml` file.
|
||||
|
||||
For instance, in order to install the Helm chart and load all the available Falco rules with automatic update on all of them, you can run
|
||||
|
||||
```
|
||||
helm install falco falcosecurity/falco --set "falcoctl.config.artifact.install.refs={falco-rules:2,falco-incubating-rules:2,falco-sandbox-rules:2}" --set "falcoctl.config.artifact.follow.refs={falco-rules:2,falco-incubating-rules:2,falco-sandbox-rules:2}" --set "falco.rules_file={/etc/falco/k8s_audit_rules.yaml,/etc/falco/rules.d,/etc/falco/falco_rules.yaml,/etc/falco/falco-incubating_rules.yaml,/etc/falco/falco-sandbox_rules.yaml}"
|
||||
```
|
||||
|
||||
Where the option `falcoctl.config.artifact.install.refs` governs which rules are downloaded at startup, `falcoctl.config.artifact.follow.refs` identifies which rules are automatically updated and `falco.rules_file` indicates which rules are loaded by the engine.
|
||||
|
||||
### Host installation
|
||||
|
||||
If you are managing your Falco installation you should be aware of which directories contain the rules. Those are governed by the `rules_file` configuration option in your [falco.yaml](https://github.com/falcosecurity/falco/blob/ab6d76e6d2a076ca1403c91aa62213d2cadb73ea/falco.yaml#L146). Normally, there is also a `rules.d` directory that you can use to upload extra rules or you can add your custom files.
|
||||
|
||||
Now you can simply download incubating or sandbox rules from the [rules](https://download.falco.org/?prefix=rules/) repository, uncompress and copy the file there.
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
If you are interested in helping and wish to contribute, we kindly request that you review our general [contribution guidelines](https://github.com/falcosecurity/.github/blob/master/CONTRIBUTING.md) and, more specifically, the dedicated [rules contributing guide](CONTRIBUTING.md) hosted in this repository. Please be aware that our reviewers will ensure compliance with the rules' acceptance criteria.
|
||||
If you are interested in helping and wish to contribute, we kindly request that you review our general [Contribution Guidelines](https://github.com/falcosecurity/.github/blob/master/CONTRIBUTING.md) and, more specifically, the dedicated [Rules Contributing](CONTRIBUTING.md) guide hosted in this repository. Please be aware that our reviewers will ensure compliance with the rules' acceptance criteria.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed to you under the [Apache 2.0 Open Source License](./LICENSE).
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2019 The Falco Authors.
|
||||
# Copyright (C) 2023 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
|
@ -22,7 +23,7 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
const defaultFalcoDockerImage = "falcosecurity/falco-no-driver:master"
|
||||
const defaultFalcoDockerImage = "falcosecurity/falco:master"
|
||||
|
||||
const defaultFalcoDockerEntrypoint = "/usr/bin/falco"
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
|
@ -28,70 +29,9 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// todo(jasondellaluce,loresuso): move this definitions and their deserialization
|
||||
// logic in falcosecurity/testing, and check for duplicates in falcoctl
|
||||
|
||||
type falcoListOutput struct {
|
||||
Details struct {
|
||||
Lists []string `json:"lists"`
|
||||
} `json:"details"`
|
||||
Info struct {
|
||||
Items []string `json:"items"`
|
||||
Name string `json:"name"`
|
||||
} `json:"info"`
|
||||
}
|
||||
|
||||
type falcoMacroOutput struct {
|
||||
Details struct {
|
||||
ConditionFields []string `json:"condition_fields"`
|
||||
Events []string `json:"events"`
|
||||
Lists []string `json:"lists"`
|
||||
Macros []string `json:"macros"`
|
||||
Operators []string `json:"operators"`
|
||||
} `json:"details"`
|
||||
Info struct {
|
||||
Condition string `json:"condition"`
|
||||
Name string `json:"name"`
|
||||
} `json:"info"`
|
||||
}
|
||||
|
||||
type falcoRuleOutput struct {
|
||||
Details struct {
|
||||
ConditionFields []string `json:"condition_fields"`
|
||||
Events []string `json:"events"`
|
||||
ExceptionFields []string `json:"exception_fields"`
|
||||
ExceptionOperators []string `json:"exception_operators"`
|
||||
Exceptions []string `json:"exceptions"`
|
||||
Lists []string `json:"lists"`
|
||||
Macros []string `json:"macros"`
|
||||
Operators []string `json:"operators"`
|
||||
OutputFields []string `json:"output_fields"`
|
||||
} `json:"details"`
|
||||
Info struct {
|
||||
Condition string `json:"condition"`
|
||||
Description string `json:"description"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Name string `json:"name"`
|
||||
Output string `json:"output"`
|
||||
Priority string `json:"priority"`
|
||||
Source string `json:"source"`
|
||||
Tags []string `json:"tags"`
|
||||
} `json:"info"`
|
||||
}
|
||||
|
||||
type falcoPluginVerReq struct {
|
||||
Name string `json:"name"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
type falcoPluginVerReqOutput struct {
|
||||
falcoPluginVerReq
|
||||
Alternatives []falcoPluginVerReq `json:"alternatives"`
|
||||
}
|
||||
|
||||
func (f *falcoPluginVerReqOutput) GetVerRequirement(pluginName string) *falcoPluginVerReq {
|
||||
func getVerRequirement(f *falco.PluginVersionRequirementDescription, pluginName string) *falco.PluginVersionRequirement {
|
||||
if f.Name == pluginName {
|
||||
return &f.falcoPluginVerReq
|
||||
return &f.PluginVersionRequirement
|
||||
}
|
||||
for _, a := range f.Alternatives {
|
||||
if a.Name == pluginName {
|
||||
|
@ -101,26 +41,18 @@ func (f *falcoPluginVerReqOutput) GetVerRequirement(pluginName string) *falcoPlu
|
|||
return nil
|
||||
}
|
||||
|
||||
func (f *falcoPluginVerReqOutput) GetRequirements() []*falcoPluginVerReq {
|
||||
var res []*falcoPluginVerReq
|
||||
res = append(res, &f.falcoPluginVerReq)
|
||||
func getRequirements(f *falco.PluginVersionRequirementDescription) []*falco.PluginVersionRequirement {
|
||||
var res []*falco.PluginVersionRequirement
|
||||
res = append(res, &f.PluginVersionRequirement)
|
||||
for _, a := range f.Alternatives {
|
||||
res = append(res, &a)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
type falcoCompareOutput struct {
|
||||
RequiredEngineVersion string `json:"required_engine_version"`
|
||||
RequiredPluginVersions []falcoPluginVerReqOutput `json:"required_plugin_versions"`
|
||||
Lists []falcoListOutput `json:"lists"`
|
||||
Macros []falcoMacroOutput `json:"macros"`
|
||||
Rules []falcoRuleOutput `json:"rules"`
|
||||
}
|
||||
|
||||
func (f *falcoCompareOutput) FindPluginVerRequirement(pluginName string) *falcoPluginVerReqOutput {
|
||||
func findPluginVerRequirement(f *falco.RulesetDescription, pluginName string) *falco.PluginVersionRequirementDescription {
|
||||
for _, r := range f.RequiredPluginVersions {
|
||||
req := r.GetVerRequirement(pluginName)
|
||||
req := getVerRequirement(&r, pluginName)
|
||||
if req != nil {
|
||||
return &r
|
||||
}
|
||||
|
@ -128,7 +60,7 @@ func (f *falcoCompareOutput) FindPluginVerRequirement(pluginName string) *falcoP
|
|||
return nil
|
||||
}
|
||||
|
||||
func (f *falcoCompareOutput) ListNames() []string {
|
||||
func listNames(f *falco.RulesetDescription) []string {
|
||||
var names []string
|
||||
for _, l := range f.Lists {
|
||||
names = append(names, l.Info.Name)
|
||||
|
@ -136,7 +68,7 @@ func (f *falcoCompareOutput) ListNames() []string {
|
|||
return names
|
||||
}
|
||||
|
||||
func (f *falcoCompareOutput) MacroNames() []string {
|
||||
func macroNames(f *falco.RulesetDescription) []string {
|
||||
var names []string
|
||||
for _, l := range f.Macros {
|
||||
names = append(names, l.Info.Name)
|
||||
|
@ -144,7 +76,7 @@ func (f *falcoCompareOutput) MacroNames() []string {
|
|||
return names
|
||||
}
|
||||
|
||||
func (f *falcoCompareOutput) RuleNames() []string {
|
||||
func ruleNames(f *falco.RulesetDescription) []string {
|
||||
var names []string
|
||||
for _, l := range f.Rules {
|
||||
names = append(names, l.Info.Name)
|
||||
|
@ -152,7 +84,7 @@ func (f *falcoCompareOutput) RuleNames() []string {
|
|||
return names
|
||||
}
|
||||
|
||||
func getCompareOutput(falcoImage, configFile string, ruleFiles, extraFiles []string) (*falcoCompareOutput, error) {
|
||||
func getCompareOutput(falcoImage, configFile string, ruleFiles, extraFiles []string) (*falco.RulesetDescription, error) {
|
||||
testOptions := []falco.TestOption{
|
||||
falco.WithOutputJSON(),
|
||||
falco.WithOutputJSON(),
|
||||
|
@ -189,7 +121,7 @@ func getCompareOutput(falcoImage, configFile string, ruleFiles, extraFiles []str
|
|||
}
|
||||
|
||||
// unmarshal json output
|
||||
var out falcoCompareOutput
|
||||
var out falco.RulesetDescription
|
||||
err = json.Unmarshal(([]byte)(res.Stdout()), &out)
|
||||
if err != nil {
|
||||
logrus.Info(res.Stderr())
|
||||
|
@ -202,7 +134,7 @@ func getCompareOutput(falcoImage, configFile string, ruleFiles, extraFiles []str
|
|||
return &out, nil
|
||||
}
|
||||
|
||||
func compareRulesPatch(left, right *falcoCompareOutput) (res []string) {
|
||||
func compareRulesPatch(left, right *falco.RulesetDescription) (res []string) {
|
||||
// Decrementing required_engine_version
|
||||
lRequiredEngineVersion, _ := strconv.Atoi(left.RequiredEngineVersion)
|
||||
rRequiredEngineVersion, _ := strconv.Atoi(right.RequiredEngineVersion)
|
||||
|
@ -214,16 +146,16 @@ func compareRulesPatch(left, right *falcoCompareOutput) (res []string) {
|
|||
// Remove or decrement plugin version requirement
|
||||
for _, lpr := range left.RequiredPluginVersions {
|
||||
var tmpRemoveRes []string
|
||||
lpReqs := lpr.GetRequirements()
|
||||
lpReqs := getRequirements(&lpr)
|
||||
for _, lr := range lpReqs {
|
||||
rr := right.FindPluginVerRequirement(lr.Name)
|
||||
rr := findPluginVerRequirement(right, lr.Name)
|
||||
if rr == nil {
|
||||
// removed dep (not an alternative)
|
||||
tmpRemoveRes = append(tmpRemoveRes, fmt.Sprintf("Version dependency to plugin `%s` has removed", lr.Name))
|
||||
} else {
|
||||
// decremented
|
||||
lv := semver.MustParse(lr.Version)
|
||||
rv := semver.MustParse(rr.GetVerRequirement(lr.Name).Version)
|
||||
rv := semver.MustParse(getVerRequirement(rr, lr.Name).Version)
|
||||
if lv.Compare(rv) > 0 {
|
||||
res = append(res, fmt.Sprintf("Version dependency to plugin `%s` has been decremented", lr.Name))
|
||||
}
|
||||
|
@ -236,17 +168,17 @@ func compareRulesPatch(left, right *falcoCompareOutput) (res []string) {
|
|||
|
||||
// Adding plugin version requirement alternative
|
||||
for _, rpr := range right.RequiredPluginVersions {
|
||||
var lrl *falcoPluginVerReqOutput
|
||||
rReqs := rpr.GetRequirements()
|
||||
var lrl *falco.PluginVersionRequirementDescription
|
||||
rReqs := getRequirements(&rpr)
|
||||
for _, rreq := range rReqs {
|
||||
lrl = left.FindPluginVerRequirement(rreq.Name)
|
||||
lrl = findPluginVerRequirement(left, rreq.Name)
|
||||
if lrl != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
if lrl != nil {
|
||||
for _, rreq := range rReqs {
|
||||
if lrl.GetVerRequirement(rreq.Name) == nil {
|
||||
if getVerRequirement(lrl, rreq.Name) == nil {
|
||||
res = append(res, fmt.Sprintf("Version dependency alternative to plugin `%s` has added", rreq.Name))
|
||||
}
|
||||
}
|
||||
|
@ -282,8 +214,8 @@ func compareRulesPatch(left, right *falcoCompareOutput) (res []string) {
|
|||
}
|
||||
|
||||
// Adding or removing exceptions for one or more Falco rules
|
||||
if len(diffStrSet(l.Details.Exceptions, r.Details.Exceptions)) != 0 ||
|
||||
len(diffStrSet(r.Details.Exceptions, l.Details.Exceptions)) != 0 {
|
||||
if len(diffStrSet(l.Details.ExceptionNames, r.Details.ExceptionNames)) != 0 ||
|
||||
len(diffStrSet(r.Details.ExceptionNames, l.Details.ExceptionNames)) != 0 {
|
||||
res = append(res, fmt.Sprintf("Rule '%s' has some exceptions added or removed", l.Info.Name))
|
||||
}
|
||||
|
||||
|
@ -306,7 +238,7 @@ func compareRulesPatch(left, right *falcoCompareOutput) (res []string) {
|
|||
return
|
||||
}
|
||||
|
||||
func compareRulesMinor(left, right *falcoCompareOutput) (res []string) {
|
||||
func compareRulesMinor(left, right *falco.RulesetDescription) (res []string) {
|
||||
// Incrementing the required_engine_version number
|
||||
l_required_engine_version, _ := strconv.Atoi(left.RequiredEngineVersion)
|
||||
r_required_engine_version, _ := strconv.Atoi(right.RequiredEngineVersion)
|
||||
|
@ -317,10 +249,10 @@ func compareRulesMinor(left, right *falcoCompareOutput) (res []string) {
|
|||
|
||||
// Adding a new plugin version requirement in required_plugin_versions
|
||||
for _, rpr := range right.RequiredPluginVersions {
|
||||
var lrl *falcoPluginVerReqOutput
|
||||
rReqs := rpr.GetRequirements()
|
||||
var lrl *falco.PluginVersionRequirementDescription
|
||||
rReqs := getRequirements(&rpr)
|
||||
for _, rreq := range rReqs {
|
||||
lrl = left.FindPluginVerRequirement(rreq.Name)
|
||||
lrl = findPluginVerRequirement(left, rreq.Name)
|
||||
if lrl != nil {
|
||||
break
|
||||
}
|
||||
|
@ -332,12 +264,12 @@ func compareRulesMinor(left, right *falcoCompareOutput) (res []string) {
|
|||
|
||||
// Incrementing the version requirement for one or more plugin
|
||||
for _, lpr := range left.RequiredPluginVersions {
|
||||
lpReqs := lpr.GetRequirements()
|
||||
lpReqs := getRequirements(&lpr)
|
||||
for _, lr := range lpReqs {
|
||||
rr := right.FindPluginVerRequirement(lr.Name)
|
||||
rr := findPluginVerRequirement(right, lr.Name)
|
||||
if rr != nil {
|
||||
lv := semver.MustParse(lr.Version)
|
||||
rv := semver.MustParse(rr.GetVerRequirement(lr.Name).Version)
|
||||
rv := semver.MustParse(getVerRequirement(rr, lr.Name).Version)
|
||||
if lv.Compare(rv) < 0 {
|
||||
res = append(res, fmt.Sprintf("Version dependency to plugin `%s` has been incremented", lr.Name))
|
||||
}
|
||||
|
@ -346,19 +278,19 @@ func compareRulesMinor(left, right *falcoCompareOutput) (res []string) {
|
|||
}
|
||||
|
||||
// Adding one or more lists, macros, or rules
|
||||
diff := diffStrSet(right.RuleNames(), left.RuleNames())
|
||||
diff := diffStrSet(ruleNames(right), ruleNames(left))
|
||||
if len(diff) > 0 {
|
||||
for v := range diff {
|
||||
res = append(res, fmt.Sprintf("Rule `%s` has been added", v))
|
||||
}
|
||||
}
|
||||
diff = diffStrSet(right.MacroNames(), left.MacroNames())
|
||||
diff = diffStrSet(macroNames(right), macroNames(left))
|
||||
if len(diff) > 0 {
|
||||
for v := range diff {
|
||||
res = append(res, fmt.Sprintf("Macro `%s` has been added", v))
|
||||
}
|
||||
}
|
||||
diff = diffStrSet(right.ListNames(), left.ListNames())
|
||||
diff = diffStrSet(listNames(right), listNames(left))
|
||||
if len(diff) > 0 {
|
||||
for v := range diff {
|
||||
res = append(res, fmt.Sprintf("List `%s` has been added", v))
|
||||
|
@ -368,13 +300,13 @@ func compareRulesMinor(left, right *falcoCompareOutput) (res []string) {
|
|||
return
|
||||
}
|
||||
|
||||
func compareRulesMajor(left, right *falcoCompareOutput) (res []string) {
|
||||
func compareRulesMajor(left, right *falco.RulesetDescription) (res []string) {
|
||||
// Remove plugin version requirement alternative
|
||||
for _, lpr := range left.RequiredPluginVersions {
|
||||
var tmpRes []string
|
||||
lpReqs := lpr.GetRequirements()
|
||||
lpReqs := getRequirements(&lpr)
|
||||
for _, lr := range lpReqs {
|
||||
rr := right.FindPluginVerRequirement(lr.Name)
|
||||
rr := findPluginVerRequirement(right, lr.Name)
|
||||
if rr == nil && len(lpr.Alternatives) > 0 {
|
||||
// removed dep (an alternative)
|
||||
tmpRes = append(tmpRes, fmt.Sprintf("Version dependency alternative to plugin `%s` has removed", lr.Name))
|
||||
|
@ -387,19 +319,19 @@ func compareRulesMajor(left, right *falcoCompareOutput) (res []string) {
|
|||
}
|
||||
|
||||
// Renaming or removing a list, macro, or rule
|
||||
diff := diffStrSet(left.RuleNames(), right.RuleNames())
|
||||
diff := diffStrSet(ruleNames(left), ruleNames(right))
|
||||
if len(diff) > 0 {
|
||||
for v := range diff {
|
||||
res = append(res, fmt.Sprintf("Rule `%s` has been removed", v))
|
||||
}
|
||||
}
|
||||
diff = diffStrSet(left.MacroNames(), right.MacroNames())
|
||||
diff = diffStrSet(macroNames(left), macroNames(right))
|
||||
if len(diff) > 0 {
|
||||
for v := range diff {
|
||||
res = append(res, fmt.Sprintf("Macro `%s` has been removed", v))
|
||||
}
|
||||
}
|
||||
diff = diffStrSet(left.ListNames(), right.ListNames())
|
||||
diff = diffStrSet(listNames(left), listNames(right))
|
||||
if len(diff) > 0 {
|
||||
for v := range diff {
|
||||
res = append(res, fmt.Sprintf("List `%s` has been removed", v))
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
|
@ -20,6 +21,7 @@ import (
|
|||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/falcosecurity/testing/pkg/falco"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
|
@ -90,8 +92,8 @@ const sampleFalcoCompareOutput = `{
|
|||
]
|
||||
}`
|
||||
|
||||
func testGetSampleFalcoCompareOutput(t *testing.T) *falcoCompareOutput {
|
||||
var out falcoCompareOutput
|
||||
func testGetSampleFalcoCompareOutput(t *testing.T) *falco.RulesetDescription {
|
||||
var out falco.RulesetDescription
|
||||
err := json.Unmarshal(([]byte)(sampleFalcoCompareOutput), &out)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
|
@ -131,7 +133,7 @@ func TestCompareRulesPatch(t *testing.T) {
|
|||
t.Run("add-plugin-version-requirement-alternative", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
o2 := testGetSampleFalcoCompareOutput(t)
|
||||
a := falcoPluginVerReq{Name: "json2", Version: "0.1.0"}
|
||||
a := falco.PluginVersionRequirement{Name: "json2", Version: "0.1.0"}
|
||||
o2.RequiredPluginVersions[1].Alternatives = append(o2.RequiredPluginVersions[1].Alternatives, a)
|
||||
res := compareRulesPatch(testGetSampleFalcoCompareOutput(t), o2)
|
||||
assert.Len(t, res, 1)
|
||||
|
@ -206,7 +208,7 @@ func TestCompareRulesPatch(t *testing.T) {
|
|||
t.Run("add-exceptions", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
o2 := testGetSampleFalcoCompareOutput(t)
|
||||
o2.Rules[0].Details.Exceptions = append(o2.Rules[0].Details.Exceptions, "some-exception-name")
|
||||
o2.Rules[0].Details.ExceptionNames = append(o2.Rules[0].Details.ExceptionNames, "some-exception-name")
|
||||
res := compareRulesPatch(testGetSampleFalcoCompareOutput(t), o2)
|
||||
assert.Len(t, res, 1)
|
||||
})
|
||||
|
@ -214,8 +216,8 @@ func TestCompareRulesPatch(t *testing.T) {
|
|||
t.Parallel()
|
||||
o1 := testGetSampleFalcoCompareOutput(t)
|
||||
o2 := testGetSampleFalcoCompareOutput(t)
|
||||
o1.Rules[0].Details.Exceptions = append(o1.Rules[0].Details.Exceptions, "exception1, exception2")
|
||||
o2.Rules[0].Details.Exceptions = append(o2.Rules[0].Details.Exceptions, "exception1")
|
||||
o1.Rules[0].Details.ExceptionNames = append(o1.Rules[0].Details.ExceptionNames, "exception1, exception2")
|
||||
o2.Rules[0].Details.ExceptionNames = append(o2.Rules[0].Details.ExceptionNames, "exception1")
|
||||
res := compareRulesPatch(o1, o2)
|
||||
assert.Len(t, res, 1)
|
||||
})
|
||||
|
@ -236,8 +238,8 @@ func TestCompareRulesMinor(t *testing.T) {
|
|||
t.Run("add-plugin-version-requirement", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
o2 := testGetSampleFalcoCompareOutput(t)
|
||||
dep := falcoPluginVerReqOutput{
|
||||
falcoPluginVerReq: falcoPluginVerReq{Name: "some_other_plugin", Version: "0.1.0"},
|
||||
dep := falco.PluginVersionRequirementDescription{
|
||||
PluginVersionRequirement: falco.PluginVersionRequirement{Name: "some_other_plugin", Version: "0.1.0"},
|
||||
}
|
||||
o2.RequiredPluginVersions = append(o2.RequiredPluginVersions, dep)
|
||||
res := compareRulesMinor(testGetSampleFalcoCompareOutput(t), o2)
|
||||
|
@ -264,7 +266,7 @@ func TestCompareRulesMinor(t *testing.T) {
|
|||
|
||||
t.Run("add-list", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
l := falcoListOutput{}
|
||||
l := falco.ListDescription{}
|
||||
l.Info.Name = "l2"
|
||||
o2 := testGetSampleFalcoCompareOutput(t)
|
||||
o2.Lists = append(o2.Lists, l)
|
||||
|
@ -274,7 +276,7 @@ func TestCompareRulesMinor(t *testing.T) {
|
|||
|
||||
t.Run("add-macro", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
l := falcoMacroOutput{}
|
||||
l := falco.MacroDescription{}
|
||||
l.Info.Name = "m2"
|
||||
o2 := testGetSampleFalcoCompareOutput(t)
|
||||
o2.Macros = append(o2.Macros, l)
|
||||
|
@ -284,7 +286,7 @@ func TestCompareRulesMinor(t *testing.T) {
|
|||
|
||||
t.Run("add-rule", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
l := falcoRuleOutput{}
|
||||
l := falco.RuleDescription{}
|
||||
l.Info.Name = "r2"
|
||||
o2 := testGetSampleFalcoCompareOutput(t)
|
||||
o2.Rules = append(o2.Rules, l)
|
||||
|
@ -294,11 +296,11 @@ func TestCompareRulesMinor(t *testing.T) {
|
|||
|
||||
t.Run("add-all", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
l := falcoListOutput{}
|
||||
l := falco.ListDescription{}
|
||||
l.Info.Name = "l2"
|
||||
m := falcoMacroOutput{}
|
||||
m := falco.MacroDescription{}
|
||||
m.Info.Name = "m2"
|
||||
r := falcoRuleOutput{}
|
||||
r := falco.RuleDescription{}
|
||||
r.Info.Name = "r2"
|
||||
o2 := testGetSampleFalcoCompareOutput(t)
|
||||
o2.Lists = append(o2.Lists, l)
|
||||
|
@ -317,7 +319,7 @@ func TestCompareRulesMajor(t *testing.T) {
|
|||
t.Run("with-alternatives", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
o2 := testGetSampleFalcoCompareOutput(t)
|
||||
o2.RequiredPluginVersions[0].Alternatives = []falcoPluginVerReq{}
|
||||
o2.RequiredPluginVersions[0].Alternatives = []falco.PluginVersionRequirement{}
|
||||
res := compareRulesMajor(testGetSampleFalcoCompareOutput(t), o2)
|
||||
assert.Len(t, res, 1)
|
||||
})
|
||||
|
@ -326,7 +328,7 @@ func TestCompareRulesMajor(t *testing.T) {
|
|||
t.Run("remove-list", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
o2 := testGetSampleFalcoCompareOutput(t)
|
||||
o2.Lists = []falcoListOutput{}
|
||||
o2.Lists = []falco.ListDescription{}
|
||||
res := compareRulesMajor(testGetSampleFalcoCompareOutput(t), o2)
|
||||
assert.Len(t, res, 1)
|
||||
})
|
||||
|
@ -334,7 +336,7 @@ func TestCompareRulesMajor(t *testing.T) {
|
|||
t.Run("remove-macro", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
o2 := testGetSampleFalcoCompareOutput(t)
|
||||
o2.Macros = []falcoMacroOutput{}
|
||||
o2.Macros = []falco.MacroDescription{}
|
||||
res := compareRulesMajor(testGetSampleFalcoCompareOutput(t), o2)
|
||||
assert.Len(t, res, 1)
|
||||
})
|
||||
|
@ -342,7 +344,7 @@ func TestCompareRulesMajor(t *testing.T) {
|
|||
t.Run("remove-rule", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
o2 := testGetSampleFalcoCompareOutput(t)
|
||||
o2.Rules = []falcoRuleOutput{}
|
||||
o2.Rules = []falco.RuleDescription{}
|
||||
res := compareRulesMajor(testGetSampleFalcoCompareOutput(t), o2)
|
||||
assert.Len(t, res, 1)
|
||||
})
|
||||
|
@ -350,9 +352,9 @@ func TestCompareRulesMajor(t *testing.T) {
|
|||
t.Run("remove-all", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
o2 := testGetSampleFalcoCompareOutput(t)
|
||||
o2.Lists = []falcoListOutput{}
|
||||
o2.Macros = []falcoMacroOutput{}
|
||||
o2.Rules = []falcoRuleOutput{}
|
||||
o2.Lists = []falco.ListDescription{}
|
||||
o2.Macros = []falco.MacroDescription{}
|
||||
o2.Rules = []falco.RuleDescription{}
|
||||
res := compareRulesMajor(testGetSampleFalcoCompareOutput(t), o2)
|
||||
assert.Len(t, res, 3)
|
||||
})
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ go 1.19
|
|||
|
||||
require (
|
||||
github.com/blang/semver v3.5.1+incompatible
|
||||
github.com/falcosecurity/testing v0.0.0-20230519163006-93666fd8e5c6
|
||||
github.com/falcosecurity/testing v0.0.0-20230929141322-214d1fbb9327
|
||||
github.com/sirupsen/logrus v1.9.0
|
||||
github.com/spf13/cobra v1.7.0
|
||||
github.com/stretchr/testify v1.8.3
|
||||
|
@ -15,7 +15,7 @@ require (
|
|||
github.com/Microsoft/go-winio v0.6.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/docker/distribution v2.8.1+incompatible // indirect
|
||||
github.com/docker/docker v20.10.23+incompatible // indirect
|
||||
github.com/docker/docker v24.0.3+incompatible // indirect
|
||||
github.com/docker/go-connections v0.4.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
|
|
|
@ -10,14 +10,16 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
|
|||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
|
||||
github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
|
||||
github.com/docker/docker v20.10.23+incompatible h1:1ZQUUYAdh+oylOT85aA2ZcfRp22jmLhoaEcVEfK8dyA=
|
||||
github.com/docker/docker v20.10.23+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/docker v24.0.3+incompatible h1:Kz/tcUmXhIojEivEoPcRWzL01tVRek7Th15/8BsRPWw=
|
||||
github.com/docker/docker v24.0.3+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
|
||||
github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
|
||||
github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
|
||||
github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
|
||||
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
|
||||
github.com/falcosecurity/testing v0.0.0-20230519163006-93666fd8e5c6 h1:htBSAnSDTxGTeomFRZuvFxUVshIyKci0t+QHsQQFlCM=
|
||||
github.com/falcosecurity/testing v0.0.0-20230519163006-93666fd8e5c6/go.mod h1:x9s7sy2h3HnQkl5lovxRgt8JR2y4nrGct8v9HZP68f0=
|
||||
github.com/falcosecurity/testing v0.0.0-20230929122211-ffc9e0c14c6b h1:4sFusgDWtUSTVa9ZY/BjZThNUdUp6m3QEPpzNfZGWVM=
|
||||
github.com/falcosecurity/testing v0.0.0-20230929122211-ffc9e0c14c6b/go.mod h1:yJVIonjfOTCI7yFQsJRU1PRFL57Ddad0HH2bo3dsiKA=
|
||||
github.com/falcosecurity/testing v0.0.0-20230929141322-214d1fbb9327 h1:AF3VgWSrzKQoYDdXzxF3F8JmV6T3y1910gcA9c0ej4E=
|
||||
github.com/falcosecurity/testing v0.0.0-20230929141322-214d1fbb9327/go.mod h1:yJVIonjfOTCI7yFQsJRU1PRFL57Ddad0HH2bo3dsiKA=
|
||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
|
@ -44,6 +46,7 @@ github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRM
|
|||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY=
|
||||
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
3.10.12
|
|
@ -0,0 +1,141 @@
|
|||
# Mitre ATT&CK Checker Module
|
||||
|
||||
The Mitre ATT&CK Checker module aims to check the compliance of the Falco rules against the Mitre ATT&CK
|
||||
framework. This module provides to Falco experts and Falco users a way to check default and custom
|
||||
rules for Mitre ATT&CK extra tags.
|
||||
This module uses STIX from the OASIS standards. Structured Threat Information Expression (STIX™) is a
|
||||
language and serialization format used to exchange cyber threat intelligence (CTI) :
|
||||
|
||||
- [STIX CTI documentation](https://oasis-open.github.io/cti-documentation/stix/intro)
|
||||
|
||||
Leveraging STIX, Mitre ATT&CK Checker fetches the ATT&CK® STIX Data from MITRE ATT&CK repositories using
|
||||
the `python-stix2` library implemented by OASIS:
|
||||
|
||||
- [ATT&CK STIX Data repository](https://github.com/mitre-attack/attack-stix-data)
|
||||
- [Python STIX2 repository](https://github.com/oasis-open/cti-python-stix2)
|
||||
|
||||
The choice of a module is motivated by the packaging of a python code to integrate it into wider Falco
|
||||
implementations. More precisely, the module can be used :
|
||||
|
||||
- by the rules_overview_generator.py script
|
||||
- by Falco users and experts to check their Falco rules files
|
||||
- by other Falco components that need to check the validity of rules files
|
||||
|
||||
## Build
|
||||
|
||||
Requirements :
|
||||
|
||||
- Python >= `3.10`
|
||||
- Poetry >= `1.5.1`
|
||||
|
||||
```sh
|
||||
./build.sh
|
||||
```
|
||||
|
||||
## Install
|
||||
|
||||
Requirements :
|
||||
|
||||
- Python >= `3.10`
|
||||
|
||||
```sh
|
||||
./install.sh
|
||||
```
|
||||
|
||||
Or manualy using `pip` :
|
||||
|
||||
```sh
|
||||
pip install dist/falco_mitre_attack_checker-0.1.0-py3-none-any.whl
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```sh
|
||||
python -m falco_mitre_attack_checker --help
|
||||
```
|
||||
|
||||
Using the stable falco rules :
|
||||
|
||||
```sh
|
||||
python -m falco_mitre_attack_checker -f ../../rules/falco_rules.yaml -o /tmp/
|
||||
```
|
||||
|
||||
## Development
|
||||
|
||||
Requirements :
|
||||
|
||||
- Python >= `3.10`
|
||||
- Poetry >= `1.5.1`
|
||||
|
||||
```sh
|
||||
poetry check
|
||||
poetry update
|
||||
poetry install --sync
|
||||
```
|
||||
|
||||
### Testing
|
||||
|
||||
With coverage :
|
||||
|
||||
```sh
|
||||
poetry update
|
||||
poetry run python -m pytest --cov=falco_mitre_attack_checker
|
||||
```
|
||||
|
||||
```
|
||||
---------- coverage: platform linux, python 3.10.12-final-0 ----------
|
||||
Name Stmts Miss Cover
|
||||
----------------------------------------------------------------------------
|
||||
falco_mitre_checker/__init__.py 0 0 100%
|
||||
falco_mitre_checker/__main__.py 7 7 0%
|
||||
falco_mitre_checker/api/__init__.py 0 0 100%
|
||||
falco_mitre_checker/api/core.py 19 19 0%
|
||||
falco_mitre_checker/cli/__init__.py 0 0 100%
|
||||
falco_mitre_checker/cli/core.py 18 18 0%
|
||||
falco_mitre_checker/engine/__init__.py 0 0 100%
|
||||
falco_mitre_checker/engine/mitre_checker.py 46 1 98%
|
||||
falco_mitre_checker/exceptions/__init__.py 0 0 100%
|
||||
falco_mitre_checker/exceptions/rules_exceptions.py 8 0 100%
|
||||
falco_mitre_checker/models/__init__.py 0 0 100%
|
||||
falco_mitre_checker/models/falco_mitre_errors.py 16 0 100%
|
||||
falco_mitre_checker/models/falco_mitre_relations.py 14 2 86%
|
||||
falco_mitre_checker/parsers/__init__.py 0 0 100%
|
||||
falco_mitre_checker/parsers/falco_rules.py 30 1 97%
|
||||
falco_mitre_checker/parsers/mitre_stix.py 31 4 87%
|
||||
falco_mitre_checker/tests/__init__.py 0 0 100%
|
||||
falco_mitre_checker/tests/engine/__init__.py 0 0 100%
|
||||
falco_mitre_checker/tests/engine/test_mitre_checker.py 41 0 100%
|
||||
falco_mitre_checker/tests/parsers/__init__.py 0 0 100%
|
||||
falco_mitre_checker/tests/parsers/test_falco_rules.py 18 0 100%
|
||||
falco_mitre_checker/tests/parsers/test_mitre_stix.py 34 0 100%
|
||||
falco_mitre_checker/tests/test_common.py 13 2 85%
|
||||
falco_mitre_checker/utils/__init__.py 0 0 100%
|
||||
falco_mitre_checker/utils/file.py 10 0 100%
|
||||
falco_mitre_checker/utils/logger.py 36 7 81%
|
||||
----------------------------------------------------------------------------
|
||||
TOTAL 341 61 82%
|
||||
```
|
||||
|
||||
### Security
|
||||
|
||||
You should run a vulnerability scanner every time you add a new dependency in projects :
|
||||
|
||||
```sh
|
||||
poetry update
|
||||
poetry run python -m safety check
|
||||
```
|
||||
|
||||
```
|
||||
Using non-commercial database
|
||||
Found and scanned 33 packages
|
||||
Timestamp 2023-10-02 13:43:51
|
||||
0 vulnerabilities found
|
||||
0 vulnerabilities ignored
|
||||
+=======================================================================================================+
|
||||
|
||||
No known security vulnerabilities found.
|
||||
|
||||
+=======================================================================================================+
|
||||
```
|
||||
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
SCRIPT_PATH="$(realpath "$0")"
|
||||
MODULE_DIR="$(dirname "${SCRIPT_PATH:?}")"
|
||||
|
||||
#
|
||||
# FUNCTIONS
|
||||
#
|
||||
|
||||
function check_requirement(){
|
||||
if ! eval "$@" >> /dev/null 2>&1 ; then
|
||||
echo "! Fatal : missing requirement"
|
||||
if [ -n "${*: -1}" ]; then echo "${@: -1}"; fi
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# MAIN
|
||||
#
|
||||
|
||||
check_requirement poetry --version "Install poetry first"
|
||||
|
||||
cd "${MODULE_DIR}" || exit
|
||||
echo "Build environment :"
|
||||
poetry env info
|
||||
|
||||
echo ""
|
||||
echo "Update dependencies"
|
||||
poetry check
|
||||
poetry update --without dev
|
||||
poetry install --without dev --sync
|
||||
|
||||
echo "Build Falco Mitre Checker module"
|
||||
rm -rf "${MODULE_DIR}/dist"
|
||||
poetry build --format wheel --no-cache
|
||||
|
||||
echo "Built in dist/:"
|
||||
ls "${MODULE_DIR}/dist/"
|
|
@ -0,0 +1,16 @@
|
|||
from falco_mitre_attack_checker.cli.core import cli
|
||||
from falco_mitre_attack_checker.utils.logger import MitreCheckerLogger
|
||||
|
||||
|
||||
def main():
|
||||
# init logger
|
||||
MitreCheckerLogger()
|
||||
# init cli
|
||||
cli()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
"""
|
||||
for debug purpose
|
||||
"""
|
||||
main()
|
|
@ -0,0 +1,38 @@
|
|||
import logging
|
||||
from pathlib import Path
|
||||
from typing import List, Dict
|
||||
|
||||
from falco_mitre_attack_checker.engine.mitre_checker import FalcoMitreChecker
|
||||
from falco_mitre_attack_checker.models.falco_mitre_errors import FalcoMitreError
|
||||
from falco_mitre_attack_checker.utils.logger import MitreCheckerLogger
|
||||
|
||||
logger = logging.getLogger(MitreCheckerLogger.name)
|
||||
|
||||
|
||||
def mitre_checker_engine(rules_files: List[Path], mitre_domain: str, mitre_version: str,
|
||||
output_dir: Path = None) -> "Dict[str, List[FalcoMitreError]]":
|
||||
"""
|
||||
CLI core function to validate the rules against the Mitre ATT&CK's data.
|
||||
:param rules_files: One or more falco rules files to check
|
||||
:param mitre_domain: The name of the Mitre ATT&CK matrix domain to validate the rules. This name is
|
||||
used to pull the data from the Mitre CTI's database.
|
||||
:param mitre_version: The version of the Mitre ATT&CK to validate the rules. This version is used to
|
||||
pull the data from the Mitre CTI's database.
|
||||
:param output_dir: A folder path to dump the errors information in json format.
|
||||
:param fix: If True, automatically generate the corrected falco rules file next to the original one
|
||||
"""
|
||||
mitre_checker = FalcoMitreChecker(mitre_domain, mitre_version)
|
||||
errors_reports: Dict[str, List[FalcoMitreError]] = {}
|
||||
for file in rules_files:
|
||||
# validate the falco rules against the data of the mitre ATT&CK framework
|
||||
errors = mitre_checker.validate(file)
|
||||
errors_reports[file.stem] = errors
|
||||
output_name = f"{file.stem}_mitre_errors.json"
|
||||
output_path = output_dir / output_name if output_dir else file.parent / output_name
|
||||
|
||||
FalcoMitreChecker.dump_errors(errors, output_path)
|
||||
logger.info(f"Dumped errors report in '{output_path}'")
|
||||
|
||||
logger.info(f"Found {len(errors)} Mitre errors")
|
||||
|
||||
return errors_reports
|
|
@ -0,0 +1,38 @@
|
|||
import logging
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
import typer
|
||||
|
||||
from falco_mitre_attack_checker.api.core import mitre_checker_engine
|
||||
from falco_mitre_attack_checker.exceptions.rules_exceptions import FalcoRulesFileContentError
|
||||
from falco_mitre_attack_checker.utils.logger import MitreCheckerLogger
|
||||
|
||||
app = typer.Typer(help=f"Mitre Checker",
|
||||
no_args_is_help=True,
|
||||
context_settings={"help_option_names": ["-h", "--help"]})
|
||||
|
||||
logger = logging.getLogger(MitreCheckerLogger.name)
|
||||
|
||||
|
||||
@app.command()
|
||||
def core(rules_files: List[Path] = typer.Option(..., "-f", "--file",
|
||||
help="Path to a Falco rules file. "
|
||||
"Repeat for multiple files validation."),
|
||||
mitre_domain: str = typer.Option("enterprise-attack", "-d", "--domain",
|
||||
help="Mitre ATT&CK domain name."),
|
||||
mitre_version: str = typer.Option("13.1", "-V", "--Version",
|
||||
help="Mitre ATT&CK domain version."),
|
||||
output_dir: Path = typer.Option(None, "-o", "--output-dir",
|
||||
help="Path to a directory to dump the error report for Mitre "
|
||||
"ATT&CK.")
|
||||
):
|
||||
try:
|
||||
mitre_checker_engine(rules_files, mitre_domain, mitre_version, output_dir)
|
||||
except FalcoRulesFileContentError as e:
|
||||
logger.error(e.message)
|
||||
typer.Exit(1)
|
||||
|
||||
|
||||
def cli():
|
||||
app()
|
|
@ -0,0 +1,111 @@
|
|||
import logging
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
from falco_mitre_attack_checker.models.falco_mitre_errors import \
|
||||
ErrorReason, FalcoMitreError, FalcoRulesErrors
|
||||
from falco_mitre_attack_checker.models.falco_mitre_relations import MitreRelations
|
||||
from falco_mitre_attack_checker.parsers.falco_rules import FalcoRulesParser
|
||||
from falco_mitre_attack_checker.parsers.mitre_stix import MitreParser
|
||||
from falco_mitre_attack_checker.utils.file import write_file
|
||||
from falco_mitre_attack_checker.utils.logger import MitreCheckerLogger
|
||||
|
||||
logger = logging.getLogger(MitreCheckerLogger.name)
|
||||
|
||||
|
||||
class FalcoMitreChecker(object):
|
||||
|
||||
def __init__(self, mitre_domain: str, mitre_domain_version: str):
|
||||
logger.info(f"Load Mitre ATT&CK STIX Data for domain '{mitre_domain}' and version "
|
||||
f"'{mitre_domain_version}'")
|
||||
self.mitre_parser = MitreParser(mitre_domain, mitre_domain_version)
|
||||
|
||||
def validate(self, falco_rules_file: Path) -> "List[FalcoMitreError]":
|
||||
"""
|
||||
This function validates the falco rules' extra tags against Mitre ATT&CK STIX Data when they
|
||||
contain mitre information.
|
||||
This method gets the mitre techniques or sub-techniques IDs and the mitre tactics (mitre phases)
|
||||
names in the extra tags of each falco rules.
|
||||
If the mitre techniques or sub-techniques IDs in the tags are not related to proper the mitre
|
||||
tactics names by comparing them with the mitre data (STIX data from Mitre CTI), this method
|
||||
considers that the rule contains an error.
|
||||
For example, if the extra tags contain :
|
||||
{"tags": ["T1611", "mitre_initial_access"] }
|
||||
And the actual mitre domain is 'enterprise-attack' in version '13.1', the tags' rule will be
|
||||
considered erroneous since the proper mitre phase for 'T1611' is 'privilege-escalation' in this
|
||||
version.
|
||||
:param falco_rules_file: A falco rule file to analyse against the Mitre ATT&CK STIX Data
|
||||
:return: A list of models containing a description of each error in the falco rules for Mitre
|
||||
ATT&CK
|
||||
"""
|
||||
logger.info(f"Audit Falco rules file '{falco_rules_file}' for Mitre ATT&CK")
|
||||
falco_rules_parser = FalcoRulesParser(falco_rules_file)
|
||||
falco_mitre_errors: List[FalcoMitreError] = []
|
||||
# build the model relation between technique (or sub-technique) ID and the mitre phase configured
|
||||
# in each rule
|
||||
rules_mitre_relations: MitreRelations = falco_rules_parser.get_mitre_relations()
|
||||
for rule_name, rule_mitre_relation in rules_mitre_relations.rules.items():
|
||||
rule_tactics = rule_mitre_relation.tactics
|
||||
all_mitre_tactics = []
|
||||
all_mitre_techniques_names = []
|
||||
all_mitre_techniques_urls = []
|
||||
|
||||
# verify each technique tag against mitre data
|
||||
for rule_technique_or_tactic in rule_mitre_relation.techniques:
|
||||
mitre_technique_or_tactic = self.mitre_parser.get_tactic_or_technique_by_id(
|
||||
rule_technique_or_tactic)
|
||||
mitre_tactics_names = self.mitre_parser.get_tactics_names(mitre_technique_or_tactic)
|
||||
formatted_mitre_tactics_names = [f"mitre_{tactic.replace('-', '_')}" for tactic in
|
||||
mitre_tactics_names]
|
||||
# gather all correct mitre tactics & techniques of this rule
|
||||
all_mitre_tactics += mitre_tactics_names
|
||||
mitre_technique_name = self.mitre_parser.get_mitre_name(mitre_technique_or_tactic)
|
||||
mitre_technique_url = self.mitre_parser.get_technique_external_reference(
|
||||
mitre_technique_or_tactic)['url']
|
||||
all_mitre_techniques_names.append(mitre_technique_name)
|
||||
all_mitre_techniques_urls.append(mitre_technique_url)
|
||||
if not set(formatted_mitre_tactics_names).issubset(set(rule_tactics)):
|
||||
# detect errors
|
||||
# missing tactic tag in rule for this technique
|
||||
falco_error = FalcoMitreError(rule=rule_name,
|
||||
techniques_tags=[rule_technique_or_tactic],
|
||||
tactics_tags=rule_tactics,
|
||||
mitre_techniques_names=[mitre_technique_name],
|
||||
mitre_tactics_names=mitre_tactics_names,
|
||||
mitre_techniques_urls=[mitre_technique_url],
|
||||
reasons=[ErrorReason.MISSING])
|
||||
|
||||
falco_mitre_errors.append(falco_error)
|
||||
|
||||
# verify tactics
|
||||
all_mitre_tactics_set = set(all_mitre_tactics)
|
||||
if len(rule_tactics) > len(all_mitre_tactics_set):
|
||||
# detect errors when too many tactic tags are included into the rule extra tags
|
||||
falco_error = FalcoMitreError(rule=rule_name,
|
||||
techniques_tags=rule_mitre_relation.techniques,
|
||||
tactics_tags=rule_tactics,
|
||||
mitre_techniques_names=list(
|
||||
set(all_mitre_techniques_names)),
|
||||
mitre_tactics_names=list(set(all_mitre_tactics_set)),
|
||||
mitre_techniques_urls=list(set(all_mitre_techniques_urls)),
|
||||
reasons=[ErrorReason.OVERDO])
|
||||
falco_mitre_errors.append(falco_error)
|
||||
|
||||
return falco_mitre_errors
|
||||
|
||||
def autofix(self, falco_rules_file: Path, falco_mitre_errors: List[FalcoMitreError]):
|
||||
"""
|
||||
Automatically fix Mitre tags in a falco rules file from a provided falco mitre errors report
|
||||
:param falco_rules_file: the rules file to fix
|
||||
:param falco_mitre_errors: the falco mitre error report for this file
|
||||
"""
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def dump_errors(falco_mitre_errors: List[FalcoMitreError], output: Path) -> None:
|
||||
"""
|
||||
Write a list of falco mitre errors model to a file
|
||||
:param output: output file to dump the errors
|
||||
:param falco_mitre_errors: List of falco mitre errors models
|
||||
"""
|
||||
write_file(FalcoRulesErrors(errors=falco_mitre_errors).json(), output)
|
|
@ -0,0 +1,12 @@
|
|||
from pathlib import Path
|
||||
|
||||
|
||||
class FalcoException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class FalcoRulesFileContentError(Exception):
|
||||
def __init__(self, file: Path, message: str = "Wrong Falco Rules file content or format", *args):
|
||||
self.file = file
|
||||
self.message = message
|
||||
super().__init__(self.message, args)
|
|
@ -0,0 +1,42 @@
|
|||
from enum import Enum
|
||||
from typing import List
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class ErrorReason(str, Enum):
|
||||
MISSING = "One or more tactics tags are missing"
|
||||
OVERDO = "Too many tactics tags"
|
||||
|
||||
|
||||
class FalcoMitreError(BaseModel):
|
||||
"""
|
||||
This model describe an error located in a falco rule and related to its mitre tag
|
||||
"""
|
||||
# FALCO RELATED INFORMATION
|
||||
# 'rule' is the rule description in the falco rules file
|
||||
rule: str
|
||||
# 'tactics_tags' are the tags of Mitre ATT&CK tactics in the current falco rule
|
||||
tactics_tags: List[str]
|
||||
# 'technique_tag' is the tag of a Mitre ATT&CK technique in the current falco rule
|
||||
techniques_tags: List[str]
|
||||
|
||||
# MITRE ATT&CK RELATED INFORMATION FROM STIX DATA
|
||||
# 'mitre_tactics_names' are the Mitre ATT&CK's tactics name related to the technique tag in the
|
||||
# current falco rule. These names are taken from STIX data.
|
||||
mitre_tactics_names: List[str]
|
||||
# 'mitre_technique_name' is the Mitre ATT&CK's technique name related to the technique tag in the
|
||||
# current falco rule. This name is taken from STIX data.
|
||||
mitre_techniques_names: List[str]
|
||||
# 'mitre_technique_url' is the Mitre ATT&CK's technique url related to the technique tag in the
|
||||
# current falco rule. This url is taken from STIX data.
|
||||
mitre_techniques_urls: List[str]
|
||||
# details about the error
|
||||
reasons: List[ErrorReason]
|
||||
|
||||
|
||||
class FalcoRulesErrors(BaseModel):
|
||||
"""
|
||||
This model is just useful to dump errors to disk
|
||||
"""
|
||||
errors: List[FalcoMitreError]
|
|
@ -0,0 +1,29 @@
|
|||
from typing import List, Dict
|
||||
|
||||
from pydantic import BaseModel
|
||||
|
||||
|
||||
class MitreRelation(BaseModel):
|
||||
"""
|
||||
Simple relation between Mitre techniques or sub-techniques and the attached mitre phases
|
||||
"""
|
||||
techniques: List[str]
|
||||
tactics: List[str]
|
||||
|
||||
|
||||
class MitreRelations(BaseModel):
|
||||
"""
|
||||
This class builds a relation between a Falco rule and the extra tags it uses for Mitre ATT&CK
|
||||
"""
|
||||
rules: Dict[str, MitreRelation] = {}
|
||||
|
||||
def __len__(self):
|
||||
return len(self.rules)
|
||||
|
||||
def add_techniques_and_tactics(self, rule_name: str, techniques_ids: List[str],
|
||||
tactics_names: List[str]):
|
||||
if rule_name in self.rules.keys():
|
||||
self.rules[rule_name].techniques += techniques_ids
|
||||
self.rules[rule_name].tactics += tactics_names
|
||||
else:
|
||||
self.rules[rule_name] = MitreRelation(techniques=techniques_ids, tactics=tactics_names)
|
|
@ -0,0 +1,52 @@
|
|||
import re
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
from falco_mitre_attack_checker.exceptions.rules_exceptions import FalcoRulesFileContentError
|
||||
from falco_mitre_attack_checker.models.falco_mitre_relations import MitreRelations
|
||||
from falco_mitre_attack_checker.utils.file import read_yaml
|
||||
|
||||
|
||||
class FalcoRulesParser(object):
|
||||
"""
|
||||
A Deserialization class for Falco rules file in order to define parsing methods
|
||||
"""
|
||||
VALIDATION_KEY = "required_engine_version"
|
||||
rules: Dict
|
||||
|
||||
def __init__(self, rules_file: Path):
|
||||
self.path = rules_file
|
||||
self.rules = read_yaml(rules_file)
|
||||
self.validate()
|
||||
|
||||
def validate(self):
|
||||
"""
|
||||
Simple function to check if the submitted file contains some requirements that Falco rules files
|
||||
should have.
|
||||
"""
|
||||
error = FalcoRulesFileContentError(self.path,
|
||||
message=f"Missing 'required_engine_version' conf in "
|
||||
f"{self.path}, so wrong falco rules file format or "
|
||||
f"not a rules file.")
|
||||
try:
|
||||
if not [items for items in self.rules if self.VALIDATION_KEY in items.keys()]:
|
||||
raise error
|
||||
except AttributeError:
|
||||
raise error
|
||||
|
||||
def get_mitre_relations(self) -> "MitreRelations":
|
||||
"""
|
||||
Build a relation model between techniques and mitre phases described in the falco rules
|
||||
:return: the list of the relations
|
||||
"""
|
||||
# filter for rules with extra tags
|
||||
filtered_rules = [rule for rule in self.rules if "tags" in rule.keys()]
|
||||
relations = MitreRelations()
|
||||
for rule in filtered_rules:
|
||||
rule_desc: str = rule['rule']
|
||||
formatted_tags = [str(tag).upper() for tag in rule['tags']]
|
||||
tactics = [tag.lower() for tag in formatted_tags if "MITRE_" in tag]
|
||||
techniques = [tag for tag in formatted_tags if re.search("^TA?(\\d+).(\\d+)", tag)]
|
||||
relations.add_techniques_and_tactics(rule_desc, techniques, tactics)
|
||||
|
||||
return relations
|
|
@ -0,0 +1,74 @@
|
|||
import logging
|
||||
from typing import Dict, List
|
||||
|
||||
import requests
|
||||
from stix2 import MemoryStore, Filter, AttackPattern
|
||||
|
||||
from falco_mitre_attack_checker.utils.logger import MitreCheckerLogger
|
||||
|
||||
logger = logging.getLogger(MitreCheckerLogger.name)
|
||||
|
||||
|
||||
class MitreParser(object):
|
||||
"""
|
||||
A Deserialization class for Mitre ATT&CK STIX2 data from Mitre CTI in order to define parsing methods
|
||||
"""
|
||||
# src is the source data directly fetched from STIX2 CTI bundle
|
||||
src: MemoryStore
|
||||
|
||||
def __init__(self, mitre_domain: str, mitre_domain_version: str):
|
||||
"""
|
||||
Init the Mitre parser by loading Mitre's STIX data from source.
|
||||
https://github.com/mitre/cti/blob/master/USAGE.md
|
||||
:param mitre_domain: either 'enterprise-attack', 'mobile-attack', or 'ics-attack'
|
||||
:param mitre_domain_version: version of the mitre domain in format 'XX.XX'
|
||||
"""
|
||||
self.mitre_domain = mitre_domain
|
||||
self.mitre_domain_version = mitre_domain_version
|
||||
stix_json = requests.get(
|
||||
f"https://raw.githubusercontent.com/mitre/cti/ATT%26CK-v{mitre_domain_version}/{mitre_domain}/{mitre_domain}.json").json()
|
||||
self.src = MemoryStore(stix_data=stix_json["objects"])
|
||||
|
||||
def get_tactic_or_technique_by_id(self, external_id: str) -> "AttackPattern | None":
|
||||
"""
|
||||
Query Mitre CTI's STIX data to search a STIX technique definition by its ID
|
||||
:param external_id: ID of the MITRE ATT&CK technique
|
||||
:return: the technique definition in STIX2 data format
|
||||
"""
|
||||
# by default, a List is returned for STIX2 refs, but we expect only one technique per ID
|
||||
try:
|
||||
technique = self.src.query([
|
||||
Filter('external_references.external_id', '=', external_id),
|
||||
Filter('type', 'in', ['x-mitre-tactic', 'attack-pattern']),
|
||||
])[0]
|
||||
# Some techniques do not contain the 'x_mitre_deprecated' field
|
||||
# So it is not exploitable with a filter, but we can do it by ourselves
|
||||
if 'x_mitre_technique' in technique:
|
||||
# return None if deprecated
|
||||
return technique if not technique.x_mitre_deprecated else None
|
||||
# considering technique is valid if no 'deprecation' field is defined
|
||||
return technique
|
||||
except IndexError:
|
||||
logger.warning(f"Technique {external_id} doesn't exist for '{self.mitre_domain}' "
|
||||
f"v{self.mitre_domain_version}")
|
||||
return None
|
||||
|
||||
@classmethod
|
||||
def get_tactics_names(cls, ttp: AttackPattern) -> "List[str]":
|
||||
"""
|
||||
Get the mitre phase name (tactic) of a given technique or tactic.
|
||||
If it is a tactic, only return the tactic name.
|
||||
:param ttp: The MITRE ATT&CK data of a technique of a tactic
|
||||
:return: The mitre phase names of the given technique or tactic
|
||||
"""
|
||||
return [tactic["phase_name"] for tactic in
|
||||
ttp["kill_chain_phases"]] if "kill_chain_phases" in ttp else [ttp["x_mitre_shortname"]]
|
||||
|
||||
@classmethod
|
||||
def get_mitre_name(cls, ttp: AttackPattern) -> str:
|
||||
return ttp['name']
|
||||
|
||||
@classmethod
|
||||
def get_technique_external_reference(cls, ttp: AttackPattern) -> "Dict[str, str]":
|
||||
return [reference for reference in ttp['external_references']
|
||||
if reference['source_name'] == "mitre-attack"][0]
|
|
@ -0,0 +1,63 @@
|
|||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
from falco_mitre_attack_checker.engine.mitre_checker import FalcoMitreChecker
|
||||
from falco_mitre_attack_checker.models.falco_mitre_errors import ErrorReason, FalcoRulesErrors, FalcoMitreError
|
||||
from falco_mitre_attack_checker.tests.test_common import MITRE_DOMAIN, MITRE_VERSION, FALCO_RULES_FILE
|
||||
|
||||
# global
|
||||
mitre_checker = FalcoMitreChecker(MITRE_DOMAIN, MITRE_VERSION)
|
||||
assert mitre_checker.mitre_parser
|
||||
|
||||
errors: List[FalcoMitreError] = mitre_checker.validate(FALCO_RULES_FILE)
|
||||
assert errors
|
||||
|
||||
|
||||
def get_errors_by_rule(rule_name: str,
|
||||
myerrors: "List[FalcoMitreError]") -> "List[FalcoMitreError]":
|
||||
return [e for e in myerrors if e.rule == rule_name]
|
||||
|
||||
|
||||
def get_error_by_technique(technique: str,
|
||||
myerrors: "List[FalcoMitreError]") -> "FalcoMitreError":
|
||||
return [e for e in myerrors if e.techniques_tags == [technique]][0]
|
||||
|
||||
|
||||
def test_validate():
|
||||
# mitre tag not matching the technique phase
|
||||
errors_1 = get_errors_by_rule('wrong mitre rule', errors)
|
||||
assert errors_1
|
||||
assert len(errors_1) == 1
|
||||
error_1: FalcoMitreError = get_error_by_technique('T1610', errors_1)
|
||||
assert error_1
|
||||
assert error_1.tactics_tags == ['mitre_lateral_movement']
|
||||
assert error_1.mitre_tactics_names == ['defense-evasion', 'execution']
|
||||
assert error_1.reasons == [ErrorReason.MISSING]
|
||||
|
||||
# missing mitre tag for multiple techniques
|
||||
# desc: one tactic tag is missing to fulfill all the mitre phases from the tagged techniques
|
||||
errors_2 = get_errors_by_rule("wrong mitre rule multiple techniques and missing one tactic", errors)
|
||||
assert len(errors_2) == 1
|
||||
error_1020: FalcoMitreError = get_error_by_technique('T1020', errors_2)
|
||||
assert error_1020
|
||||
assert error_1020.tactics_tags == ['mitre_credential_access', 'mitre_discovery']
|
||||
assert error_1020.mitre_tactics_names == ['exfiltration']
|
||||
assert error_1020.reasons == [ErrorReason.MISSING]
|
||||
|
||||
# too many tactics tags
|
||||
errors_3 = get_errors_by_rule("too many tactics tags with multiple techniques", errors)
|
||||
assert len(errors_3) == 1
|
||||
error_tactics: FalcoMitreError = errors_3[0]
|
||||
assert error_tactics.tactics_tags.sort() == ["mitre_discovery", "mitre_exfiltration",
|
||||
"mitre_credential_access", "mitre_execution"].sort()
|
||||
assert error_tactics.mitre_tactics_names.sort() == ["mitre_discovery", "mitre_exfiltration",
|
||||
"mitre_credential_access"].sort()
|
||||
assert error_tactics.reasons == [ErrorReason.OVERDO]
|
||||
|
||||
|
||||
def test_dump():
|
||||
output = Path('/tmp/test_falco_mitre_checker_dump.json')
|
||||
mitre_checker.dump_errors(errors, output)
|
||||
assert output.exists()
|
||||
from_file = FalcoRulesErrors.parse_file(output)
|
||||
assert from_file
|
|
@ -0,0 +1,26 @@
|
|||
import pytest
|
||||
|
||||
from falco_mitre_attack_checker.exceptions.rules_exceptions import FalcoRulesFileContentError
|
||||
from falco_mitre_attack_checker.parsers.falco_rules import FalcoRulesParser
|
||||
from falco_mitre_attack_checker.tests.test_common import NOT_FALCO_RULES_FILE, FALCO_RULES_FILE
|
||||
|
||||
# test falco rules file validation
|
||||
with pytest.raises(FalcoRulesFileContentError):
|
||||
FalcoRulesParser(NOT_FALCO_RULES_FILE)
|
||||
|
||||
falco_rules_parser = FalcoRulesParser(FALCO_RULES_FILE)
|
||||
assert falco_rules_parser.rules
|
||||
|
||||
|
||||
def test_get_mitre_relations():
|
||||
relations = falco_rules_parser.get_mitre_relations()
|
||||
assert relations
|
||||
assert len(relations) == 6
|
||||
|
||||
correct_mitre_rule = relations.rules['correct mitre rule']
|
||||
assert correct_mitre_rule.tactics == ['mitre_persistence']
|
||||
assert correct_mitre_rule.techniques == ['T1098']
|
||||
|
||||
wrong_mitre_rule = relations.rules['wrong mitre rule']
|
||||
assert wrong_mitre_rule.tactics == ['mitre_lateral_movement']
|
||||
assert wrong_mitre_rule.techniques == ['T1610']
|
|
@ -0,0 +1,50 @@
|
|||
from falco_mitre_attack_checker.parsers.mitre_stix import MitreParser
|
||||
from falco_mitre_attack_checker.tests.test_common import RESOURCES_DIR, MITRE_VERSION, MITRE_DOMAIN
|
||||
|
||||
MITRE_STIX_DATAFILE = f"{RESOURCES_DIR}/mitre_cti_stix_13_1.json"
|
||||
|
||||
mitre_parser = MitreParser(MITRE_DOMAIN, MITRE_VERSION)
|
||||
assert mitre_parser.src
|
||||
|
||||
|
||||
def test_get_tactic_or_technique_by_id():
|
||||
# technique
|
||||
technique = mitre_parser.get_tactic_or_technique_by_id("T1548.001")
|
||||
assert technique
|
||||
assert not bool(technique.x_mitre_deprecated)
|
||||
assert technique.type == 'attack-pattern'
|
||||
assert technique.kill_chain_phases
|
||||
kill_chain_names = [chain.kill_chain_name for chain in technique.kill_chain_phases]
|
||||
assert 'mitre-attack' in kill_chain_names
|
||||
|
||||
# tactic
|
||||
tactic = mitre_parser.get_tactic_or_technique_by_id("TA0001")
|
||||
assert tactic
|
||||
assert tactic['type'] == "x-mitre-tactic"
|
||||
|
||||
|
||||
def test_get_mitre_name():
|
||||
technique = mitre_parser.get_tactic_or_technique_by_id("T1548.001")
|
||||
assert mitre_parser.get_mitre_name(technique) == "Setuid and Setgid"
|
||||
|
||||
|
||||
def test_get_technique_external_reference():
|
||||
technique = mitre_parser.get_tactic_or_technique_by_id("T1548.001")
|
||||
reference = mitre_parser.get_technique_external_reference(technique)
|
||||
assert reference
|
||||
assert reference['source_name'] == 'mitre-attack'
|
||||
assert reference['url'] == "https://attack.mitre.org/techniques/T1548/001"
|
||||
|
||||
|
||||
def test_get_tactics_names():
|
||||
# technique with multiple tactics
|
||||
technique = mitre_parser.get_tactic_or_technique_by_id("T1610")
|
||||
tactics_names = mitre_parser.get_tactics_names(technique)
|
||||
assert tactics_names
|
||||
assert tactics_names == ['defense-evasion', 'execution']
|
||||
|
||||
# tactic
|
||||
tactic = mitre_parser.get_tactic_or_technique_by_id("TA0001")
|
||||
tactics_names = mitre_parser.get_tactics_names(tactic)
|
||||
assert tactics_names
|
||||
assert tactics_names == ['initial-access']
|
|
@ -0,0 +1,88 @@
|
|||
- required_engine_version: 0.31.0
|
||||
|
||||
- macro: not a rule
|
||||
condition: true
|
||||
|
||||
- rule: not a mitre rule
|
||||
desc: an attempt to write to any file below /etc
|
||||
condition: write_etc_common
|
||||
output: "File below /etc opened for writing (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid parent=%proc.pname pcmdline=%proc.pcmdline file=%fd.name program=%proc.name gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] container_id=%container.id image=%container.image.repository)"
|
||||
priority: ERROR
|
||||
tags: [ host, container, filesystem ]
|
||||
|
||||
- rule: correct mitre rule
|
||||
desc: an attempt to write to any file below /etc
|
||||
condition: write_etc_common
|
||||
output: "File below /etc opened for writing (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid parent=%proc.pname pcmdline=%proc.pcmdline file=%fd.name program=%proc.name gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] container_id=%container.id image=%container.image.repository)"
|
||||
priority: ERROR
|
||||
tags: [ host, container, network, mitre_persistence, T1098 ]
|
||||
|
||||
- rule: wrong mitre rule
|
||||
desc: >
|
||||
Detect the initial process started by a container that is not in a list of allowed containers.
|
||||
condition: container_started and container and not allowed_containers
|
||||
output: Container started and not in allowed list (user=%user.name user_loginuid=%user.loginuid command=%proc.cmdline pid=%proc.pid %container.info image=%container.image.repository:%container.image.tag)
|
||||
priority: WARNING
|
||||
tags: [ container, mitre_lateral_movement, T1610 ]
|
||||
|
||||
- rule: correct mitre rule tactics tags with multiple techniques
|
||||
desc: >
|
||||
Directory traversal monitored file read - Web applications can be vulnerable to directory traversal attacks that allow accessing files outside of the web app's root directory (e.g. Arbitrary File Read bugs).
|
||||
System directories like /etc are typically accessed via absolute paths. Access patterns outside of this (here path traversal) can be regarded as suspicious.
|
||||
This rule includes failed file open attempts.
|
||||
condition: (open_read or open_file_failed) and (etc_dir or user_ssh_directory or fd.name startswith /root/.ssh or fd.name contains "id_rsa") and directory_traversal and not proc.pname in (shell_binaries)
|
||||
enabled: true
|
||||
output: >
|
||||
Read monitored file via directory traversal (username=%user.name useruid=%user.uid user_loginuid=%user.loginuid program=%proc.name exe=%proc.exepath
|
||||
command=%proc.cmdline pid=%proc.pid parent=%proc.pname file=%fd.name fileraw=%fd.nameraw parent=%proc.pname
|
||||
gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository returncode=%evt.res cwd=%proc.cwd)
|
||||
priority: WARNING
|
||||
tags: [ host, container, filesystem, mitre_discovery, mitre_exfiltration, mitre_credential_access, T1555, T1212, T1020, T1552, T1083 ]
|
||||
|
||||
- rule: too many tactics tags with multiple techniques
|
||||
desc: >
|
||||
Directory traversal monitored file read - Web applications can be vulnerable to directory traversal attacks that allow accessing files outside of the web app's root directory (e.g. Arbitrary File Read bugs).
|
||||
System directories like /etc are typically accessed via absolute paths. Access patterns outside of this (here path traversal) can be regarded as suspicious.
|
||||
This rule includes failed file open attempts.
|
||||
condition: (open_read or open_file_failed) and (etc_dir or user_ssh_directory or fd.name startswith /root/.ssh or fd.name contains "id_rsa") and directory_traversal and not proc.pname in (shell_binaries)
|
||||
enabled: true
|
||||
output: >
|
||||
Read monitored file via directory traversal (username=%user.name useruid=%user.uid user_loginuid=%user.loginuid program=%proc.name exe=%proc.exepath
|
||||
command=%proc.cmdline pid=%proc.pid parent=%proc.pname file=%fd.name fileraw=%fd.nameraw parent=%proc.pname
|
||||
gparent=%proc.aname[2] container_id=%container.id image=%container.image.repository returncode=%evt.res cwd=%proc.cwd)
|
||||
priority: WARNING
|
||||
tags: [ host, container, filesystem, mitre_discovery, mitre_exfiltration, mitre_credential_access, mitre_execution, T1555, T1212, T1020, T1552, T1083 ]
|
||||
|
||||
- rule: wrong mitre rule multiple techniques and missing one tactic
|
||||
desc: >
|
||||
Read sensitive file untrusted - an attempt to read any sensitive file (e.g. files containing user/password/authentication
|
||||
information). Exceptions are made for known trusted programs.
|
||||
condition: >
|
||||
sensitive_files and open_read
|
||||
and proc_name_exists
|
||||
and not proc.name in (user_mgmt_binaries, userexec_binaries, package_mgmt_binaries,
|
||||
cron_binaries, read_sensitive_file_binaries, shell_binaries, hids_binaries,
|
||||
vpn_binaries, mail_config_binaries, nomachine_binaries, sshkit_script_binaries,
|
||||
in.proftpd, mandb, salt-call, salt-minion, postgres_mgmt_binaries,
|
||||
google_oslogin_
|
||||
)
|
||||
and not cmp_cp_by_passwd
|
||||
and not ansible_running_python
|
||||
and not run_by_qualys
|
||||
and not run_by_chef
|
||||
and not run_by_google_accounts_daemon
|
||||
and not user_read_sensitive_file_conditions
|
||||
and not mandb_postinst
|
||||
and not perl_running_plesk
|
||||
and not perl_running_updmap
|
||||
and not veritas_driver_script
|
||||
and not perl_running_centrifydc
|
||||
and not runuser_reading_pam
|
||||
and not linux_bench_reading_etc_shadow
|
||||
and not user_known_read_sensitive_files_activities
|
||||
and not user_read_sensitive_file_containers
|
||||
output: >
|
||||
Sensitive file opened for reading by non-trusted program (user=%user.name user_loginuid=%user.loginuid program=%proc.name
|
||||
command=%proc.cmdline pid=%proc.pid file=%fd.name parent=%proc.pname gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] container_id=%container.id image=%container.image.repository)
|
||||
priority: WARNING
|
||||
tags: [ host, container, filesystem, mitre_credential_access, mitre_discovery, T1555, T1212, T1020, T1552, T1083 ]
|
|
@ -0,0 +1,2 @@
|
|||
test: True
|
||||
falco-rules: false
|
|
@ -0,0 +1,20 @@
|
|||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from falco_mitre_attack_checker.utils.logger import MitreCheckerLogger
|
||||
|
||||
MitreCheckerLogger()
|
||||
|
||||
TEST_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
RESOURCES_DIR = f"{TEST_DIR}/resources"
|
||||
|
||||
MITRE_VERSION = "13.1"
|
||||
MITRE_DOMAIN = "enterprise-attack"
|
||||
|
||||
FALCO_RULES_FILE = Path(f"{RESOURCES_DIR}/falco_rules_test.yaml")
|
||||
NOT_FALCO_RULES_FILE = Path(f"{RESOURCES_DIR}/not_falco_rules_test.yaml")
|
||||
|
||||
|
||||
def read_file(path: Path) -> "str":
|
||||
with open(path, 'r') as f:
|
||||
return str(f.read())
|
|
@ -0,0 +1,20 @@
|
|||
import os
|
||||
from pathlib import Path
|
||||
from typing import Dict
|
||||
|
||||
import yaml
|
||||
|
||||
|
||||
def read_yaml(path: Path) -> Dict:
|
||||
"""
|
||||
Validate format and read yaml file content
|
||||
:param path: Path to a yaml file
|
||||
:return: file content as dictionnary
|
||||
"""
|
||||
with open(path, "r") as p:
|
||||
return yaml.safe_load(p.read())
|
||||
|
||||
|
||||
def write_file(content: str, output: Path):
|
||||
with open(os.path.expandvars(output), 'w') as f:
|
||||
f.write(content)
|
|
@ -0,0 +1,55 @@
|
|||
import logging
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class LoggerFormatter(logging.Formatter):
|
||||
green = "\x1b[92;21m"
|
||||
cyan = "\x1b[96;21m"
|
||||
yellow = "\x1b[93;21m"
|
||||
red = "\x1b[91;21m"
|
||||
reset = "\x1b[0m"
|
||||
tag = "[%(levelname)s]"
|
||||
message = " %(message)s"
|
||||
file = " - (%(filename)s:%(lineno)d)"
|
||||
|
||||
FORMATS = {
|
||||
logging.DEBUG: cyan + tag + reset + message,
|
||||
logging.INFO: green + tag + reset + message,
|
||||
logging.WARNING: yellow + tag + reset + message + file,
|
||||
logging.ERROR: red + tag + reset + message + file,
|
||||
logging.FATAL: red + tag + reset + message + file
|
||||
}
|
||||
|
||||
def format(self, record):
|
||||
log_fmt = self.FORMATS.get(record.levelno)
|
||||
formatter = logging.Formatter(log_fmt)
|
||||
return formatter.format(record)
|
||||
|
||||
|
||||
class MitreCheckerLogger:
|
||||
name: str = "mitre-checker"
|
||||
formatter: logging.Formatter = LoggerFormatter()
|
||||
|
||||
def __init__(self, debug: bool = False, logfile: Optional[Path] = None):
|
||||
logger = logging.getLogger(self.name)
|
||||
|
||||
# verbosity
|
||||
level = logging.DEBUG if debug else logging.INFO
|
||||
logger.setLevel(level)
|
||||
|
||||
# add stdout logger to logging
|
||||
stdout_handler = logging.StreamHandler(sys.stdout)
|
||||
stdout_handler.setFormatter(self.formatter)
|
||||
logger.addHandler(stdout_handler)
|
||||
|
||||
# logfile output
|
||||
if logfile is not None:
|
||||
logfile_path = Path(logfile)
|
||||
logfile_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
logfile_path.touch(exist_ok=True)
|
||||
output_file_handler = logging.FileHandler(logfile)
|
||||
output_file_handler.setLevel(level)
|
||||
output_file_handler.setFormatter(self.formatter)
|
||||
logger.addHandler(output_file_handler)
|
|
@ -0,0 +1,31 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
SCRIPT_PATH="$(realpath "$0")"
|
||||
MODULE_DIR="$(dirname "${SCRIPT_PATH:?}")"
|
||||
|
||||
#
|
||||
# FUNCTIONS
|
||||
#
|
||||
|
||||
function check_requirement(){
|
||||
if ! eval "$@" >> /dev/null 2>&1 ; then
|
||||
echo "! Fatal : missing requirement"
|
||||
if [ -n "${*: -1}" ]; then echo "${@: -1}"; fi
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
#
|
||||
# MAIN
|
||||
#
|
||||
|
||||
cd "${MODULE_DIR}" || exit
|
||||
pyversion=$(python --version)
|
||||
echo "Install falco mitre checker module for: ${pyversion}"
|
||||
|
||||
echo ""
|
||||
wheel="$(find "./dist/" -type f -name "*.whl")"
|
||||
python -m pip install "${wheel}" --force-reinstall --no-cache-dir
|
||||
|
||||
echo ""
|
||||
echo "OK"
|
|
@ -0,0 +1,823 @@
|
|||
# This file is automatically @generated by Poetry 1.5.1 and should not be changed by hand.
|
||||
|
||||
[[package]]
|
||||
name = "antlr4-python3-runtime"
|
||||
version = "4.9.3"
|
||||
description = "ANTLR 4.9.3 runtime for Python 3.7"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "antlr4-python3-runtime-4.9.3.tar.gz", hash = "sha256:f224469b4168294902bb1efa80a8bf7855f24c99aef99cbefc1bcd3cce77881b"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "certifi"
|
||||
version = "2023.11.17"
|
||||
description = "Python package for providing Mozilla's CA Bundle."
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"},
|
||||
{file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "charset-normalizer"
|
||||
version = "3.3.2"
|
||||
description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet."
|
||||
optional = false
|
||||
python-versions = ">=3.7.0"
|
||||
files = [
|
||||
{file = "charset-normalizer-3.3.2.tar.gz", hash = "sha256:f30c3cb33b24454a82faecaf01b19c18562b1e89558fb6c56de4d9118a032fd5"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:25baf083bf6f6b341f4121c2f3c548875ee6f5339300e08be3f2b2ba1721cdd3"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:06435b539f889b1f6f4ac1758871aae42dc3a8c0e24ac9e60c2384973ad73027"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9063e24fdb1e498ab71cb7419e24622516c4a04476b17a2dab57e8baa30d6e03"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6897af51655e3691ff853668779c7bad41579facacf5fd7253b0133308cf000d"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1d3193f4a680c64b4b6a9115943538edb896edc190f0b222e73761716519268e"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cd70574b12bb8a4d2aaa0094515df2463cb429d8536cfb6c7ce983246983e5a6"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8465322196c8b4d7ab6d1e049e4c5cb460d0394da4a27d23cc242fbf0034b6b5"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a9a8e9031d613fd2009c182b69c7b2c1ef8239a0efb1df3f7c8da66d5dd3d537"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:beb58fe5cdb101e3a055192ac291b7a21e3b7ef4f67fa1d74e331a7f2124341c"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:e06ed3eb3218bc64786f7db41917d4e686cc4856944f53d5bdf83a6884432e12"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:2e81c7b9c8979ce92ed306c249d46894776a909505d8f5a4ba55b14206e3222f"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:572c3763a264ba47b3cf708a44ce965d98555f618ca42c926a9c1616d8f34269"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fd1abc0d89e30cc4e02e4064dc67fcc51bd941eb395c502aac3ec19fab46b519"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-win32.whl", hash = "sha256:3d47fa203a7bd9c5b6cee4736ee84ca03b8ef23193c0d1ca99b5089f72645c73"},
|
||||
{file = "charset_normalizer-3.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:10955842570876604d404661fbccbc9c7e684caf432c09c715ec38fbae45ae09"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:802fe99cca7457642125a8a88a084cef28ff0cf9407060f7b93dca5aa25480db"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:573f6eac48f4769d667c4442081b1794f52919e7edada77495aaed9236d13a96"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:549a3a73da901d5bc3ce8d24e0600d1fa85524c10287f6004fbab87672bf3e1e"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f27273b60488abe721a075bcca6d7f3964f9f6f067c8c4c605743023d7d3944f"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ceae2f17a9c33cb48e3263960dc5fc8005351ee19db217e9b1bb15d28c02574"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:65f6f63034100ead094b8744b3b97965785388f308a64cf8d7c34f2f2e5be0c4"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:753f10e867343b4511128c6ed8c82f7bec3bd026875576dfd88483c5c73b2fd8"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a78b2b446bd7c934f5dcedc588903fb2f5eec172f3d29e52a9096a43722adfc"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:e537484df0d8f426ce2afb2d0f8e1c3d0b114b83f8850e5f2fbea0e797bd82ae"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:eb6904c354526e758fda7167b33005998fb68c46fbc10e013ca97f21ca5c8887"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:deb6be0ac38ece9ba87dea880e438f25ca3eddfac8b002a2ec3d9183a454e8ae"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:4ab2fe47fae9e0f9dee8c04187ce5d09f48eabe611be8259444906793ab7cbce"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:80402cd6ee291dcb72644d6eac93785fe2c8b9cb30893c1af5b8fdd753b9d40f"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-win32.whl", hash = "sha256:7cd13a2e3ddeed6913a65e66e94b51d80a041145a026c27e6bb76c31a853c6ab"},
|
||||
{file = "charset_normalizer-3.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:663946639d296df6a2bb2aa51b60a2454ca1cb29835324c640dafb5ff2131a77"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0b2b64d2bb6d3fb9112bafa732def486049e63de9618b5843bcdd081d8144cd8"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:ddbb2551d7e0102e7252db79ba445cdab71b26640817ab1e3e3648dad515003b"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:55086ee1064215781fff39a1af09518bc9255b50d6333f2e4c74ca09fac6a8f6"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8f4a014bc36d3c57402e2977dada34f9c12300af536839dc38c0beab8878f38a"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a10af20b82360ab00827f916a6058451b723b4e65030c5a18577c8b2de5b3389"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d756e44e94489e49571086ef83b2bb8ce311e730092d2c34ca8f7d925cb20aa"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:90d558489962fd4918143277a773316e56c72da56ec7aa3dc3dbbe20fdfed15b"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ac7ffc7ad6d040517be39eb591cac5ff87416c2537df6ba3cba3bae290c0fed"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7ed9e526742851e8d5cc9e6cf41427dfc6068d4f5a3bb03659444b4cabf6bc26"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8bdb58ff7ba23002a4c5808d608e4e6c687175724f54a5dade5fa8c67b604e4d"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:6b3251890fff30ee142c44144871185dbe13b11bab478a88887a639655be1068"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:b4a23f61ce87adf89be746c8a8974fe1c823c891d8f86eb218bb957c924bb143"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:efcb3f6676480691518c177e3b465bcddf57cea040302f9f4e6e191af91174d4"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-win32.whl", hash = "sha256:d965bba47ddeec8cd560687584e88cf699fd28f192ceb452d1d7ee807c5597b7"},
|
||||
{file = "charset_normalizer-3.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:96b02a3dc4381e5494fad39be677abcb5e6634bf7b4fa83a6dd3112607547001"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:95f2a5796329323b8f0512e09dbb7a1860c46a39da62ecb2324f116fa8fdc85c"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c002b4ffc0be611f0d9da932eb0f704fe2602a9a949d1f738e4c34c75b0863d5"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a981a536974bbc7a512cf44ed14938cf01030a99e9b3a06dd59578882f06f985"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3287761bc4ee9e33561a7e058c72ac0938c4f57fe49a09eae428fd88aafe7bb6"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:42cb296636fcc8b0644486d15c12376cb9fa75443e00fb25de0b8602e64c1714"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0a55554a2fa0d408816b3b5cedf0045f4b8e1a6065aec45849de2d6f3f8e9786"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:c083af607d2515612056a31f0a8d9e0fcb5876b7bfc0abad3ecd275bc4ebc2d5"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:87d1351268731db79e0f8e745d92493ee2841c974128ef629dc518b937d9194c"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:bd8f7df7d12c2db9fab40bdd87a7c09b1530128315d047a086fa3ae3435cb3a8"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:c180f51afb394e165eafe4ac2936a14bee3eb10debc9d9e4db8958fe36afe711"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8c622a5fe39a48f78944a87d4fb8a53ee07344641b0562c540d840748571b811"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-win32.whl", hash = "sha256:db364eca23f876da6f9e16c9da0df51aa4f104a972735574842618b8c6d999d4"},
|
||||
{file = "charset_normalizer-3.3.2-cp37-cp37m-win_amd64.whl", hash = "sha256:86216b5cee4b06df986d214f664305142d9c76df9b6512be2738aa72a2048f99"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:6463effa3186ea09411d50efc7d85360b38d5f09b870c48e4600f63af490e56a"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6c4caeef8fa63d06bd437cd4bdcf3ffefe6738fb1b25951440d80dc7df8c03ac"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37e55c8e51c236f95b033f6fb391d7d7970ba5fe7ff453dad675e88cf303377a"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fb69256e180cb6c8a894fee62b3afebae785babc1ee98b81cdf68bbca1987f33"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ae5f4161f18c61806f411a13b0310bea87f987c7d2ecdbdaad0e94eb2e404238"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b2b0a0c0517616b6869869f8c581d4eb2dd83a4d79e0ebcb7d373ef9956aeb0a"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:45485e01ff4d3630ec0d9617310448a8702f70e9c01906b0d0118bdf9d124cf2"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eb00ed941194665c332bf8e078baf037d6c35d7c4f3102ea2d4f16ca94a26dc8"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2127566c664442652f024c837091890cb1942c30937add288223dc895793f898"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a50aebfa173e157099939b17f18600f72f84eed3049e743b68ad15bd69b6bf99"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4d0d1650369165a14e14e1e47b372cfcb31d6ab44e6e33cb2d4e57265290044d"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:923c0c831b7cfcb071580d3f46c4baf50f174be571576556269530f4bbd79d04"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:06a81e93cd441c56a9b65d8e1d043daeb97a3d0856d177d5c90ba85acb3db087"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-win32.whl", hash = "sha256:6ef1d82a3af9d3eecdba2321dc1b3c238245d890843e040e41e470ffa64c3e25"},
|
||||
{file = "charset_normalizer-3.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:eb8821e09e916165e160797a6c17edda0679379a4be5c716c260e836e122f54b"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c235ebd9baae02f1b77bcea61bce332cb4331dc3617d254df3323aa01ab47bd4"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5b4c145409bef602a690e7cfad0a15a55c13320ff7a3ad7ca59c13bb8ba4d45d"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:68d1f8a9e9e37c1223b656399be5d6b448dea850bed7d0f87a8311f1ff3dabb0"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22afcb9f253dac0696b5a4be4a1c0f8762f8239e21b99680099abd9b2b1b2269"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e27ad930a842b4c5eb8ac0016b0a54f5aebbe679340c26101df33424142c143c"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f79682fbe303db92bc2b1136016a38a42e835d932bab5b3b1bfcfbf0640e519"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b261ccdec7821281dade748d088bb6e9b69e6d15b30652b74cbbac25e280b796"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:122c7fa62b130ed55f8f285bfd56d5f4b4a5b503609d181f9ad85e55c89f4185"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d0eccceffcb53201b5bfebb52600a5fb483a20b61da9dbc885f8b103cbe7598c"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f96df6923e21816da7e0ad3fd47dd8f94b2a5ce594e00677c0013018b813458"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:7f04c839ed0b6b98b1a7501a002144b76c18fb1c1850c8b98d458ac269e26ed2"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:34d1c8da1e78d2e001f363791c98a272bb734000fcef47a491c1e3b0505657a8"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ff8fa367d09b717b2a17a052544193ad76cd49979c805768879cb63d9ca50561"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-win32.whl", hash = "sha256:aed38f6e4fb3f5d6bf81bfa990a07806be9d83cf7bacef998ab1a9bd660a581f"},
|
||||
{file = "charset_normalizer-3.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b01b88d45a6fcb69667cd6d2f7a9aeb4bf53760d7fc536bf679ec94fe9f3ff3d"},
|
||||
{file = "charset_normalizer-3.3.2-py3-none-any.whl", hash = "sha256:3e4d1f6587322d2788836a99c69062fbb091331ec940e02d12d179c1d53e25fc"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "click"
|
||||
version = "8.1.7"
|
||||
description = "Composable command line interface toolkit"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
|
||||
{file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = "*", markers = "platform_system == \"Windows\""}
|
||||
|
||||
[[package]]
|
||||
name = "colorama"
|
||||
version = "0.4.6"
|
||||
description = "Cross-platform colored terminal text."
|
||||
optional = false
|
||||
python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
|
||||
files = [
|
||||
{file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
|
||||
{file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "coverage"
|
||||
version = "7.3.2"
|
||||
description = "Code coverage measurement for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "coverage-7.3.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d872145f3a3231a5f20fd48500274d7df222e291d90baa2026cc5152b7ce86bf"},
|
||||
{file = "coverage-7.3.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:310b3bb9c91ea66d59c53fa4989f57d2436e08f18fb2f421a1b0b6b8cc7fffda"},
|
||||
{file = "coverage-7.3.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f47d39359e2c3779c5331fc740cf4bce6d9d680a7b4b4ead97056a0ae07cb49a"},
|
||||
{file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa72dbaf2c2068404b9870d93436e6d23addd8bbe9295f49cbca83f6e278179c"},
|
||||
{file = "coverage-7.3.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:beaa5c1b4777f03fc63dfd2a6bd820f73f036bfb10e925fce067b00a340d0f3f"},
|
||||
{file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:dbc1b46b92186cc8074fee9d9fbb97a9dd06c6cbbef391c2f59d80eabdf0faa6"},
|
||||
{file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:315a989e861031334d7bee1f9113c8770472db2ac484e5b8c3173428360a9148"},
|
||||
{file = "coverage-7.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d1bc430677773397f64a5c88cb522ea43175ff16f8bfcc89d467d974cb2274f9"},
|
||||
{file = "coverage-7.3.2-cp310-cp310-win32.whl", hash = "sha256:a889ae02f43aa45032afe364c8ae84ad3c54828c2faa44f3bfcafecb5c96b02f"},
|
||||
{file = "coverage-7.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:c0ba320de3fb8c6ec16e0be17ee1d3d69adcda99406c43c0409cb5c41788a611"},
|
||||
{file = "coverage-7.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ac8c802fa29843a72d32ec56d0ca792ad15a302b28ca6203389afe21f8fa062c"},
|
||||
{file = "coverage-7.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:89a937174104339e3a3ffcf9f446c00e3a806c28b1841c63edb2b369310fd074"},
|
||||
{file = "coverage-7.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e267e9e2b574a176ddb983399dec325a80dbe161f1a32715c780b5d14b5f583a"},
|
||||
{file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2443cbda35df0d35dcfb9bf8f3c02c57c1d6111169e3c85fc1fcc05e0c9f39a3"},
|
||||
{file = "coverage-7.3.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4175e10cc8dda0265653e8714b3174430b07c1dca8957f4966cbd6c2b1b8065a"},
|
||||
{file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0cbf38419fb1a347aaf63481c00f0bdc86889d9fbf3f25109cf96c26b403fda1"},
|
||||
{file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5c913b556a116b8d5f6ef834038ba983834d887d82187c8f73dec21049abd65c"},
|
||||
{file = "coverage-7.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1981f785239e4e39e6444c63a98da3a1db8e971cb9ceb50a945ba6296b43f312"},
|
||||
{file = "coverage-7.3.2-cp311-cp311-win32.whl", hash = "sha256:43668cabd5ca8258f5954f27a3aaf78757e6acf13c17604d89648ecc0cc66640"},
|
||||
{file = "coverage-7.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10c39c0452bf6e694511c901426d6b5ac005acc0f78ff265dbe36bf81f808a2"},
|
||||
{file = "coverage-7.3.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4cbae1051ab791debecc4a5dcc4a1ff45fc27b91b9aee165c8a27514dd160836"},
|
||||
{file = "coverage-7.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:12d15ab5833a997716d76f2ac1e4b4d536814fc213c85ca72756c19e5a6b3d63"},
|
||||
{file = "coverage-7.3.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3c7bba973ebee5e56fe9251300c00f1579652587a9f4a5ed8404b15a0471f216"},
|
||||
{file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fe494faa90ce6381770746077243231e0b83ff3f17069d748f645617cefe19d4"},
|
||||
{file = "coverage-7.3.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6e9589bd04d0461a417562649522575d8752904d35c12907d8c9dfeba588faf"},
|
||||
{file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d51ac2a26f71da1b57f2dc81d0e108b6ab177e7d30e774db90675467c847bbdf"},
|
||||
{file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99b89d9f76070237975b315b3d5f4d6956ae354a4c92ac2388a5695516e47c84"},
|
||||
{file = "coverage-7.3.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:fa28e909776dc69efb6ed975a63691bc8172b64ff357e663a1bb06ff3c9b589a"},
|
||||
{file = "coverage-7.3.2-cp312-cp312-win32.whl", hash = "sha256:289fe43bf45a575e3ab10b26d7b6f2ddb9ee2dba447499f5401cfb5ecb8196bb"},
|
||||
{file = "coverage-7.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:7dbc3ed60e8659bc59b6b304b43ff9c3ed858da2839c78b804973f613d3e92ed"},
|
||||
{file = "coverage-7.3.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f94b734214ea6a36fe16e96a70d941af80ff3bfd716c141300d95ebc85339738"},
|
||||
{file = "coverage-7.3.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:af3d828d2c1cbae52d34bdbb22fcd94d1ce715d95f1a012354a75e5913f1bda2"},
|
||||
{file = "coverage-7.3.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:630b13e3036e13c7adc480ca42fa7afc2a5d938081d28e20903cf7fd687872e2"},
|
||||
{file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c9eacf273e885b02a0273bb3a2170f30e2d53a6d53b72dbe02d6701b5296101c"},
|
||||
{file = "coverage-7.3.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8f17966e861ff97305e0801134e69db33b143bbfb36436efb9cfff6ec7b2fd9"},
|
||||
{file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b4275802d16882cf9c8b3d057a0839acb07ee9379fa2749eca54efbce1535b82"},
|
||||
{file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:72c0cfa5250f483181e677ebc97133ea1ab3eb68645e494775deb6a7f6f83901"},
|
||||
{file = "coverage-7.3.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:cb536f0dcd14149425996821a168f6e269d7dcd2c273a8bff8201e79f5104e76"},
|
||||
{file = "coverage-7.3.2-cp38-cp38-win32.whl", hash = "sha256:307adb8bd3abe389a471e649038a71b4eb13bfd6b7dd9a129fa856f5c695cf92"},
|
||||
{file = "coverage-7.3.2-cp38-cp38-win_amd64.whl", hash = "sha256:88ed2c30a49ea81ea3b7f172e0269c182a44c236eb394718f976239892c0a27a"},
|
||||
{file = "coverage-7.3.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b631c92dfe601adf8f5ebc7fc13ced6bb6e9609b19d9a8cd59fa47c4186ad1ce"},
|
||||
{file = "coverage-7.3.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d3d9df4051c4a7d13036524b66ecf7a7537d14c18a384043f30a303b146164e9"},
|
||||
{file = "coverage-7.3.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f7363d3b6a1119ef05015959ca24a9afc0ea8a02c687fe7e2d557705375c01f"},
|
||||
{file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2f11cc3c967a09d3695d2a6f03fb3e6236622b93be7a4b5dc09166a861be6d25"},
|
||||
{file = "coverage-7.3.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:149de1d2401ae4655c436a3dced6dd153f4c3309f599c3d4bd97ab172eaf02d9"},
|
||||
{file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3a4006916aa6fee7cd38db3bfc95aa9c54ebb4ffbfc47c677c8bba949ceba0a6"},
|
||||
{file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9028a3871280110d6e1aa2df1afd5ef003bab5fb1ef421d6dc748ae1c8ef2ebc"},
|
||||
{file = "coverage-7.3.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9f805d62aec8eb92bab5b61c0f07329275b6f41c97d80e847b03eb894f38d083"},
|
||||
{file = "coverage-7.3.2-cp39-cp39-win32.whl", hash = "sha256:d1c88ec1a7ff4ebca0219f5b1ef863451d828cccf889c173e1253aa84b1e07ce"},
|
||||
{file = "coverage-7.3.2-cp39-cp39-win_amd64.whl", hash = "sha256:b4767da59464bb593c07afceaddea61b154136300881844768037fd5e859353f"},
|
||||
{file = "coverage-7.3.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:ae97af89f0fbf373400970c0a21eef5aa941ffeed90aee43650b81f7d7f47637"},
|
||||
{file = "coverage-7.3.2.tar.gz", hash = "sha256:be32ad29341b0170e795ca590e1c07e81fc061cb5b10c74ce7203491484404ef"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
tomli = {version = "*", optional = true, markers = "python_full_version <= \"3.11.0a6\" and extra == \"toml\""}
|
||||
|
||||
[package.extras]
|
||||
toml = ["tomli"]
|
||||
|
||||
[[package]]
|
||||
name = "dparse"
|
||||
version = "0.6.3"
|
||||
description = "A parser for Python dependency files"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "dparse-0.6.3-py3-none-any.whl", hash = "sha256:0d8fe18714056ca632d98b24fbfc4e9791d4e47065285ab486182288813a5318"},
|
||||
{file = "dparse-0.6.3.tar.gz", hash = "sha256:27bb8b4bcaefec3997697ba3f6e06b2447200ba273c0b085c3d012a04571b528"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
packaging = "*"
|
||||
tomli = {version = "*", markers = "python_version < \"3.11\""}
|
||||
|
||||
[package.extras]
|
||||
conda = ["pyyaml"]
|
||||
pipenv = ["pipenv (<=2022.12.19)"]
|
||||
|
||||
[[package]]
|
||||
name = "exceptiongroup"
|
||||
version = "1.2.0"
|
||||
description = "Backport of PEP 654 (exception groups)"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "exceptiongroup-1.2.0-py3-none-any.whl", hash = "sha256:4bfd3996ac73b41e9b9628b04e079f193850720ea5945fc96a08633c66912f14"},
|
||||
{file = "exceptiongroup-1.2.0.tar.gz", hash = "sha256:91f5c769735f051a4290d52edd0858999b57e5876e9f85937691bd4c9fa3ed68"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
test = ["pytest (>=6)"]
|
||||
|
||||
[[package]]
|
||||
name = "idna"
|
||||
version = "3.6"
|
||||
description = "Internationalized Domain Names in Applications (IDNA)"
|
||||
optional = false
|
||||
python-versions = ">=3.5"
|
||||
files = [
|
||||
{file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"},
|
||||
{file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iniconfig"
|
||||
version = "2.0.0"
|
||||
description = "brain-dead simple config-ini parsing"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "iniconfig-2.0.0-py3-none-any.whl", hash = "sha256:b6a85871a79d2e3b22d2d1b94ac2824226a63c6b741c88f7ae975f18b6778374"},
|
||||
{file = "iniconfig-2.0.0.tar.gz", hash = "sha256:2d91e135bf72d31a410b17c16da610a82cb55f6b0477d1a902134b24a455b8b3"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "21.3"
|
||||
description = "Core utilities for Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"},
|
||||
{file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
pyparsing = ">=2.0.2,<3.0.5 || >3.0.5"
|
||||
|
||||
[[package]]
|
||||
name = "pluggy"
|
||||
version = "1.3.0"
|
||||
description = "plugin and hook calling mechanisms for python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"},
|
||||
{file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
dev = ["pre-commit", "tox"]
|
||||
testing = ["pytest", "pytest-benchmark"]
|
||||
|
||||
[[package]]
|
||||
name = "pydantic"
|
||||
version = "1.10.13"
|
||||
description = "Data validation and settings management using python type hints"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "pydantic-1.10.13-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:efff03cc7a4f29d9009d1c96ceb1e7a70a65cfe86e89d34e4a5f2ab1e5693737"},
|
||||
{file = "pydantic-1.10.13-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3ecea2b9d80e5333303eeb77e180b90e95eea8f765d08c3d278cd56b00345d01"},
|
||||
{file = "pydantic-1.10.13-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1740068fd8e2ef6eb27a20e5651df000978edce6da6803c2bef0bc74540f9548"},
|
||||
{file = "pydantic-1.10.13-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84bafe2e60b5e78bc64a2941b4c071a4b7404c5c907f5f5a99b0139781e69ed8"},
|
||||
{file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bc0898c12f8e9c97f6cd44c0ed70d55749eaf783716896960b4ecce2edfd2d69"},
|
||||
{file = "pydantic-1.10.13-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:654db58ae399fe6434e55325a2c3e959836bd17a6f6a0b6ca8107ea0571d2e17"},
|
||||
{file = "pydantic-1.10.13-cp310-cp310-win_amd64.whl", hash = "sha256:75ac15385a3534d887a99c713aa3da88a30fbd6204a5cd0dc4dab3d770b9bd2f"},
|
||||
{file = "pydantic-1.10.13-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c553f6a156deb868ba38a23cf0df886c63492e9257f60a79c0fd8e7173537653"},
|
||||
{file = "pydantic-1.10.13-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5e08865bc6464df8c7d61439ef4439829e3ab62ab1669cddea8dd00cd74b9ffe"},
|
||||
{file = "pydantic-1.10.13-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e31647d85a2013d926ce60b84f9dd5300d44535a9941fe825dc349ae1f760df9"},
|
||||
{file = "pydantic-1.10.13-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:210ce042e8f6f7c01168b2d84d4c9eb2b009fe7bf572c2266e235edf14bacd80"},
|
||||
{file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8ae5dd6b721459bfa30805f4c25880e0dd78fc5b5879f9f7a692196ddcb5a580"},
|
||||
{file = "pydantic-1.10.13-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:f8e81fc5fb17dae698f52bdd1c4f18b6ca674d7068242b2aff075f588301bbb0"},
|
||||
{file = "pydantic-1.10.13-cp311-cp311-win_amd64.whl", hash = "sha256:61d9dce220447fb74f45e73d7ff3b530e25db30192ad8d425166d43c5deb6df0"},
|
||||
{file = "pydantic-1.10.13-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4b03e42ec20286f052490423682016fd80fda830d8e4119f8ab13ec7464c0132"},
|
||||
{file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f59ef915cac80275245824e9d771ee939133be38215555e9dc90c6cb148aaeb5"},
|
||||
{file = "pydantic-1.10.13-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5a1f9f747851338933942db7af7b6ee8268568ef2ed86c4185c6ef4402e80ba8"},
|
||||
{file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:97cce3ae7341f7620a0ba5ef6cf043975cd9d2b81f3aa5f4ea37928269bc1b87"},
|
||||
{file = "pydantic-1.10.13-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:854223752ba81e3abf663d685f105c64150873cc6f5d0c01d3e3220bcff7d36f"},
|
||||
{file = "pydantic-1.10.13-cp37-cp37m-win_amd64.whl", hash = "sha256:b97c1fac8c49be29486df85968682b0afa77e1b809aff74b83081cc115e52f33"},
|
||||
{file = "pydantic-1.10.13-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c958d053453a1c4b1c2062b05cd42d9d5c8eb67537b8d5a7e3c3032943ecd261"},
|
||||
{file = "pydantic-1.10.13-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4c5370a7edaac06daee3af1c8b1192e305bc102abcbf2a92374b5bc793818599"},
|
||||
{file = "pydantic-1.10.13-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7d6f6e7305244bddb4414ba7094ce910560c907bdfa3501e9db1a7fd7eaea127"},
|
||||
{file = "pydantic-1.10.13-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3a3c792a58e1622667a2837512099eac62490cdfd63bd407993aaf200a4cf1f"},
|
||||
{file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:c636925f38b8db208e09d344c7aa4f29a86bb9947495dd6b6d376ad10334fb78"},
|
||||
{file = "pydantic-1.10.13-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:678bcf5591b63cc917100dc50ab6caebe597ac67e8c9ccb75e698f66038ea953"},
|
||||
{file = "pydantic-1.10.13-cp38-cp38-win_amd64.whl", hash = "sha256:6cf25c1a65c27923a17b3da28a0bdb99f62ee04230c931d83e888012851f4e7f"},
|
||||
{file = "pydantic-1.10.13-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8ef467901d7a41fa0ca6db9ae3ec0021e3f657ce2c208e98cd511f3161c762c6"},
|
||||
{file = "pydantic-1.10.13-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:968ac42970f57b8344ee08837b62f6ee6f53c33f603547a55571c954a4225691"},
|
||||
{file = "pydantic-1.10.13-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9849f031cf8a2f0a928fe885e5a04b08006d6d41876b8bbd2fc68a18f9f2e3fd"},
|
||||
{file = "pydantic-1.10.13-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:56e3ff861c3b9c6857579de282ce8baabf443f42ffba355bf070770ed63e11e1"},
|
||||
{file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9f00790179497767aae6bcdc36355792c79e7bbb20b145ff449700eb076c5f96"},
|
||||
{file = "pydantic-1.10.13-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:75b297827b59bc229cac1a23a2f7a4ac0031068e5be0ce385be1462e7e17a35d"},
|
||||
{file = "pydantic-1.10.13-cp39-cp39-win_amd64.whl", hash = "sha256:e70ca129d2053fb8b728ee7d1af8e553a928d7e301a311094b8a0501adc8763d"},
|
||||
{file = "pydantic-1.10.13-py3-none-any.whl", hash = "sha256:b87326822e71bd5f313e7d3bfdc77ac3247035ac10b0c0618bd99dcf95b1e687"},
|
||||
{file = "pydantic-1.10.13.tar.gz", hash = "sha256:32c8b48dcd3b2ac4e78b0ba4af3a2c2eb6048cb75202f0ea7b34feb740efc340"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
typing-extensions = ">=4.2.0"
|
||||
|
||||
[package.extras]
|
||||
dotenv = ["python-dotenv (>=0.10.4)"]
|
||||
email = ["email-validator (>=1.0.3)"]
|
||||
|
||||
[[package]]
|
||||
name = "pyparsing"
|
||||
version = "3.1.1"
|
||||
description = "pyparsing module - Classes and methods to define and execute parsing grammars"
|
||||
optional = false
|
||||
python-versions = ">=3.6.8"
|
||||
files = [
|
||||
{file = "pyparsing-3.1.1-py3-none-any.whl", hash = "sha256:32c7c0b711493c72ff18a981d24f28aaf9c1fb7ed5e9667c9e84e3db623bdbfb"},
|
||||
{file = "pyparsing-3.1.1.tar.gz", hash = "sha256:ede28a1a32462f5a9705e07aea48001a08f7cf81a021585011deba701581a0db"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
diagrams = ["jinja2", "railroad-diagrams"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest"
|
||||
version = "7.4.3"
|
||||
description = "pytest: simple powerful testing with Python"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "pytest-7.4.3-py3-none-any.whl", hash = "sha256:0d009c083ea859a71b76adf7c1d502e4bc170b80a8ef002da5806527b9591fac"},
|
||||
{file = "pytest-7.4.3.tar.gz", hash = "sha256:d989d136982de4e3b29dabcc838ad581c64e8ed52c11fbe86ddebd9da0818cd5"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
colorama = {version = "*", markers = "sys_platform == \"win32\""}
|
||||
exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""}
|
||||
iniconfig = "*"
|
||||
packaging = "*"
|
||||
pluggy = ">=0.12,<2.0"
|
||||
tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""}
|
||||
|
||||
[package.extras]
|
||||
testing = ["argcomplete", "attrs (>=19.2.0)", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-cov"
|
||||
version = "4.1.0"
|
||||
description = "Pytest plugin for measuring coverage."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "pytest-cov-4.1.0.tar.gz", hash = "sha256:3904b13dfbfec47f003b8e77fd5b589cd11904a21ddf1ab38a64f204d6a10ef6"},
|
||||
{file = "pytest_cov-4.1.0-py3-none-any.whl", hash = "sha256:6ba70b9e97e69fcc3fb45bfeab2d0a138fb65c4d0d6a41ef33983ad114be8c3a"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
coverage = {version = ">=5.2.1", extras = ["toml"]}
|
||||
pytest = ">=4.6"
|
||||
|
||||
[package.extras]
|
||||
testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"]
|
||||
|
||||
[[package]]
|
||||
name = "pytz"
|
||||
version = "2023.3.post1"
|
||||
description = "World timezone definitions, modern and historical"
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "pytz-2023.3.post1-py2.py3-none-any.whl", hash = "sha256:ce42d816b81b68506614c11e8937d3aa9e41007ceb50bfdcb0749b921bf646c7"},
|
||||
{file = "pytz-2023.3.post1.tar.gz", hash = "sha256:7b4fddbeb94a1eba4b557da24f19fdf9db575192544270a9101d8509f9f43d7b"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pyyaml"
|
||||
version = "6.0.1"
|
||||
description = "YAML parser and emitter for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:d858aa552c999bc8a8d57426ed01e40bef403cd8ccdd0fc5f6f04a00414cac2a"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:fd66fc5d0da6d9815ba2cebeb4205f95818ff4b79c3ebe268e75d961704af52f"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69b023b2b4daa7548bcfbd4aa3da05b3a74b772db9e23b982788168117739938"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:81e0b275a9ecc9c0c0c07b4b90ba548307583c125f54d5b6946cfee6360c733d"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba336e390cd8e4d1739f42dfe9bb83a3cc2e80f567d8805e11b46f4a943f5515"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-win32.whl", hash = "sha256:bd4af7373a854424dabd882decdc5579653d7868b8fb26dc7d0e99f823aa5924"},
|
||||
{file = "PyYAML-6.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:fd1592b3fdf65fff2ad0004b5e363300ef59ced41c2e6b3a99d4089fa8c5435d"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:6965a7bc3cf88e5a1c3bd2e0b5c22f8d677dc88a455344035f03399034eb3007"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f003ed9ad21d6a4713f0a9b5a7a0a79e08dd0f221aff4525a2be4c346ee60aab"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:42f8152b8dbc4fe7d96729ec2b99c7097d656dc1213a3229ca5383f973a5ed6d"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:062582fca9fabdd2c8b54a3ef1c978d786e0f6b3a1510e0ac93ef59e0ddae2bc"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d2b04aac4d386b172d5b9692e2d2da8de7bfb6c387fa4f801fbf6fb2e6ba4673"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-win32.whl", hash = "sha256:1635fd110e8d85d55237ab316b5b011de701ea0f29d07611174a1b42f1444741"},
|
||||
{file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:50550eb667afee136e9a77d6dc71ae76a44df8b3e51e41b77f6de2932bfe0f47"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1fe35611261b29bd1de0070f0b2f47cb6ff71fa6595c077e42bd0c419fa27b98"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:704219a11b772aea0d8ecd7058d0082713c3562b4e271b849ad7dc4a5c90c13c"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:afd7e57eddb1a54f0f1a974bc4391af8bcce0b444685d936840f125cf046d5bd"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-win32.whl", hash = "sha256:fca0e3a251908a499833aa292323f32437106001d436eca0e6e7833256674585"},
|
||||
{file = "PyYAML-6.0.1-cp36-cp36m-win_amd64.whl", hash = "sha256:f22ac1c3cac4dbc50079e965eba2c1058622631e526bd9afd45fedd49ba781fa"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b1275ad35a5d18c62a7220633c913e1b42d44b46ee12554e5fd39c70a243d6a3"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18aeb1bf9a78867dc38b259769503436b7c72f7a1f1f4c93ff9a17de54319b27"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:596106435fa6ad000c2991a98fa58eeb8656ef2325d7e158344fb33864ed87e3"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:baa90d3f661d43131ca170712d903e6295d1f7a0f595074f151c0aed377c9b9c"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-win32.whl", hash = "sha256:9046c58c4395dff28dd494285c82ba00b546adfc7ef001486fbf0324bc174fba"},
|
||||
{file = "PyYAML-6.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:4fb147e7a67ef577a588a0e2c17b6db51dda102c71de36f8549b6816a96e1867"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1d4c7e777c441b20e32f52bd377e0c409713e8bb1386e1099c2415f26e479595"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a0cd17c15d3bb3fa06978b4e8958dcdc6e0174ccea823003a106c7d4d7899ac5"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:28c119d996beec18c05208a8bd78cbe4007878c6dd15091efb73a30e90539696"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7e07cbde391ba96ab58e532ff4803f79c4129397514e1413a7dc761ccd755735"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-win32.whl", hash = "sha256:184c5108a2aca3c5b3d3bf9395d50893a7ab82a38004c8f61c258d4428e80206"},
|
||||
{file = "PyYAML-6.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:1e2722cc9fbb45d9b87631ac70924c11d3a401b2d7f410cc0e3bbf249f2dca62"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9eb6caa9a297fc2c2fb8862bc5370d0303ddba53ba97e71f08023b6cd73d16a8"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c8098ddcc2a85b61647b2590f825f3db38891662cfc2fc776415143f599bb859"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5773183b6446b2c99bb77e77595dd486303b4faab2b086e7b17bc6bef28865f6"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b786eecbdf8499b9ca1d697215862083bd6d2a99965554781d0d8d1ad31e13a0"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc1bf2925a1ecd43da378f4db9e4f799775d6367bdb94671027b73b393a7c42c"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-win32.whl", hash = "sha256:faca3bdcf85b2fc05d06ff3fbc1f83e1391b3e724afa3feba7d13eeab355484c"},
|
||||
{file = "PyYAML-6.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:510c9deebc5c0225e8c96813043e62b680ba2f9c50a08d3724c7f28a747d1486"},
|
||||
{file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "requests"
|
||||
version = "2.31.0"
|
||||
description = "Python HTTP for Humans."
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"},
|
||||
{file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
certifi = ">=2017.4.17"
|
||||
charset-normalizer = ">=2,<4"
|
||||
idna = ">=2.5,<4"
|
||||
urllib3 = ">=1.21.1,<3"
|
||||
|
||||
[package.extras]
|
||||
socks = ["PySocks (>=1.5.6,!=1.5.7)"]
|
||||
use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
|
||||
|
||||
[[package]]
|
||||
name = "ruamel-yaml"
|
||||
version = "0.18.5"
|
||||
description = "ruamel.yaml is a YAML parser/emitter that supports roundtrip preservation of comments, seq/map flow style, and map key order"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "ruamel.yaml-0.18.5-py3-none-any.whl", hash = "sha256:a013ac02f99a69cdd6277d9664689eb1acba07069f912823177c5eced21a6ada"},
|
||||
{file = "ruamel.yaml-0.18.5.tar.gz", hash = "sha256:61917e3a35a569c1133a8f772e1226961bf5a1198bea7e23f06a0841dea1ab0e"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
"ruamel.yaml.clib" = {version = ">=0.2.7", markers = "platform_python_implementation == \"CPython\" and python_version < \"3.13\""}
|
||||
|
||||
[package.extras]
|
||||
docs = ["mercurial (>5.7)", "ryd"]
|
||||
jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"]
|
||||
|
||||
[[package]]
|
||||
name = "ruamel-yaml-clib"
|
||||
version = "0.2.8"
|
||||
description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:b42169467c42b692c19cf539c38d4602069d8c1505e97b86387fcf7afb766e1d"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp310-cp310-macosx_13_0_arm64.whl", hash = "sha256:07238db9cbdf8fc1e9de2489a4f68474e70dffcb32232db7c08fa61ca0c7c462"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:fff3573c2db359f091e1589c3d7c5fc2f86f5bdb6f24252c2d8e539d4e45f412"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp310-cp310-manylinux_2_24_aarch64.whl", hash = "sha256:aa2267c6a303eb483de8d02db2871afb5c5fc15618d894300b88958f729ad74f"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:840f0c7f194986a63d2c2465ca63af8ccbbc90ab1c6001b1978f05119b5e7334"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:024cfe1fc7c7f4e1aff4a81e718109e13409767e4f871443cbff3dba3578203d"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win32.whl", hash = "sha256:c69212f63169ec1cfc9bb44723bf2917cbbd8f6191a00ef3410f5a7fe300722d"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp310-cp310-win_amd64.whl", hash = "sha256:cabddb8d8ead485e255fe80429f833172b4cadf99274db39abc080e068cbcc31"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:bef08cd86169d9eafb3ccb0a39edb11d8e25f3dae2b28f5c52fd997521133069"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp311-cp311-macosx_13_0_arm64.whl", hash = "sha256:b16420e621d26fdfa949a8b4b47ade8810c56002f5389970db4ddda51dbff248"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:25c515e350e5b739842fc3228d662413ef28f295791af5e5110b543cf0b57d9b"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp311-cp311-manylinux_2_24_aarch64.whl", hash = "sha256:1707814f0d9791df063f8c19bb51b0d1278b8e9a2353abbb676c2f685dee6afe"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:46d378daaac94f454b3a0e3d8d78cafd78a026b1d71443f4966c696b48a6d899"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:09b055c05697b38ecacb7ac50bdab2240bfca1a0c4872b0fd309bb07dc9aa3a9"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win32.whl", hash = "sha256:53a300ed9cea38cf5a2a9b069058137c2ca1ce658a874b79baceb8f892f915a7"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp311-cp311-win_amd64.whl", hash = "sha256:c2a72e9109ea74e511e29032f3b670835f8a59bbdc9ce692c5b4ed91ccf1eedb"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:ebc06178e8821efc9692ea7544aa5644217358490145629914d8020042c24aa1"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp312-cp312-macosx_13_0_arm64.whl", hash = "sha256:edaef1c1200c4b4cb914583150dcaa3bc30e592e907c01117c08b13a07255ec2"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d176b57452ab5b7028ac47e7b3cf644bcfdc8cacfecf7e71759f7f51a59e5c92"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp312-cp312-manylinux_2_24_aarch64.whl", hash = "sha256:1dc67314e7e1086c9fdf2680b7b6c2be1c0d8e3a8279f2e993ca2a7545fecf62"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:3213ece08ea033eb159ac52ae052a4899b56ecc124bb80020d9bbceeb50258e9"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:aab7fd643f71d7946f2ee58cc88c9b7bfc97debd71dcc93e03e2d174628e7e2d"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win32.whl", hash = "sha256:5c365d91c88390c8d0a8545df0b5857172824b1c604e867161e6b3d59a827eaa"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp312-cp312-win_amd64.whl", hash = "sha256:1758ce7d8e1a29d23de54a16ae867abd370f01b5a69e1a3ba75223eaa3ca1a1b"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:a5aa27bad2bb83670b71683aae140a1f52b0857a2deff56ad3f6c13a017a26ed"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c58ecd827313af6864893e7af0a3bb85fd529f862b6adbefe14643947cfe2942"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f481f16baec5290e45aebdc2a5168ebc6d35189ae6fea7a58787613a25f6e875"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_24_aarch64.whl", hash = "sha256:77159f5d5b5c14f7c34073862a6b7d34944075d9f93e681638f6d753606c6ce6"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:7f67a1ee819dc4562d444bbafb135832b0b909f81cc90f7aa00260968c9ca1b3"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:4ecbf9c3e19f9562c7fdd462e8d18dd902a47ca046a2e64dba80699f0b6c09b7"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:87ea5ff66d8064301a154b3933ae406b0863402a799b16e4a1d24d9fbbcbe0d3"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win32.whl", hash = "sha256:75e1ed13e1f9de23c5607fe6bd1aeaae21e523b32d83bb33918245361e9cc51b"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp37-cp37m-win_amd64.whl", hash = "sha256:3f215c5daf6a9d7bbed4a0a4f760f3113b10e82ff4c5c44bec20a68c8014f675"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1b617618914cb00bf5c34d4357c37aa15183fa229b24767259657746c9077615"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:a6a9ffd280b71ad062eae53ac1659ad86a17f59a0fdc7699fd9be40525153337"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_24_aarch64.whl", hash = "sha256:305889baa4043a09e5b76f8e2a51d4ffba44259f6b4c72dec8ca56207d9c6fe1"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:700e4ebb569e59e16a976857c8798aee258dceac7c7d6b50cab63e080058df91"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:e2b4c44b60eadec492926a7270abb100ef9f72798e18743939bdbf037aab8c28"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e79e5db08739731b0ce4850bed599235d601701d5694c36570a99a0c5ca41a9d"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win32.whl", hash = "sha256:955eae71ac26c1ab35924203fda6220f84dce57d6d7884f189743e2abe3a9fbe"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp38-cp38-win_amd64.whl", hash = "sha256:56f4252222c067b4ce51ae12cbac231bce32aee1d33fbfc9d17e5b8d6966c312"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:03d1162b6d1df1caa3a4bd27aa51ce17c9afc2046c31b0ad60a0a96ec22f8001"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:bba64af9fa9cebe325a62fa398760f5c7206b215201b0ec825005f1b18b9bccf"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_24_aarch64.whl", hash = "sha256:a1a45e0bb052edf6a1d3a93baef85319733a888363938e1fc9924cb00c8df24c"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.whl", hash = "sha256:da09ad1c359a728e112d60116f626cc9f29730ff3e0e7db72b9a2dbc2e4beed5"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:184565012b60405d93838167f425713180b949e9d8dd0bbc7b49f074407c5a8b"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a75879bacf2c987c003368cf14bed0ffe99e8e85acfa6c0bfffc21a090f16880"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win32.whl", hash = "sha256:84b554931e932c46f94ab306913ad7e11bba988104c5cff26d90d03f68258cd5"},
|
||||
{file = "ruamel.yaml.clib-0.2.8-cp39-cp39-win_amd64.whl", hash = "sha256:25ac8c08322002b06fa1d49d1646181f0b2c72f5cbc15a85e80b4c30a544bb15"},
|
||||
{file = "ruamel.yaml.clib-0.2.8.tar.gz", hash = "sha256:beb2e0404003de9a4cab9753a8805a8fe9320ee6673136ed7f04255fe60bb512"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "safety"
|
||||
version = "2.3.5"
|
||||
description = "Checks installed dependencies for known vulnerabilities and licenses."
|
||||
optional = false
|
||||
python-versions = "*"
|
||||
files = [
|
||||
{file = "safety-2.3.5-py3-none-any.whl", hash = "sha256:2227fcac1b22b53c1615af78872b48348661691450aa25d6704a5504dbd1f7e2"},
|
||||
{file = "safety-2.3.5.tar.gz", hash = "sha256:a60c11f8952f412cbb165d70cb1f673a3b43a2ba9a93ce11f97e6a4de834aa3a"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
Click = ">=8.0.2"
|
||||
dparse = ">=0.6.2"
|
||||
packaging = ">=21.0,<22.0"
|
||||
requests = "*"
|
||||
"ruamel.yaml" = ">=0.17.21"
|
||||
setuptools = ">=19.3"
|
||||
|
||||
[package.extras]
|
||||
github = ["jinja2 (>=3.1.0)", "pygithub (>=1.43.3)"]
|
||||
gitlab = ["python-gitlab (>=1.3.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "setuptools"
|
||||
version = "69.0.2"
|
||||
description = "Easily download, build, install, upgrade, and uninstall Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "setuptools-69.0.2-py3-none-any.whl", hash = "sha256:1e8fdff6797d3865f37397be788a4e3cba233608e9b509382a2777d25ebde7f2"},
|
||||
{file = "setuptools-69.0.2.tar.gz", hash = "sha256:735896e78a4742605974de002ac60562d286fa8051a7e2299445e8e8fbb01aa6"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"]
|
||||
testing = ["build[virtualenv]", "filelock (>=3.4.0)", "flake8-2020", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "pip (>=19.1)", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf", "pytest-ruff", "pytest-timeout", "pytest-xdist", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"]
|
||||
testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.1)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"]
|
||||
|
||||
[[package]]
|
||||
name = "simplejson"
|
||||
version = "3.19.2"
|
||||
description = "Simple, fast, extensible JSON encoder/decoder for Python"
|
||||
optional = false
|
||||
python-versions = ">=2.5, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
files = [
|
||||
{file = "simplejson-3.19.2-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:3471e95110dcaf901db16063b2e40fb394f8a9e99b3fe9ee3acc6f6ef72183a2"},
|
||||
{file = "simplejson-3.19.2-cp27-cp27m-manylinux1_i686.whl", hash = "sha256:3194cd0d2c959062b94094c0a9f8780ffd38417a5322450a0db0ca1a23e7fbd2"},
|
||||
{file = "simplejson-3.19.2-cp27-cp27m-manylinux1_x86_64.whl", hash = "sha256:8a390e56a7963e3946ff2049ee1eb218380e87c8a0e7608f7f8790ba19390867"},
|
||||
{file = "simplejson-3.19.2-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:1537b3dd62d8aae644f3518c407aa8469e3fd0f179cdf86c5992792713ed717a"},
|
||||
{file = "simplejson-3.19.2-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:a8617625369d2d03766413bff9e64310feafc9fc4f0ad2b902136f1a5cd8c6b0"},
|
||||
{file = "simplejson-3.19.2-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:2c433a412e96afb9a3ce36fa96c8e61a757af53e9c9192c97392f72871e18e69"},
|
||||
{file = "simplejson-3.19.2-cp27-cp27mu-manylinux1_x86_64.whl", hash = "sha256:f1c70249b15e4ce1a7d5340c97670a95f305ca79f376887759b43bb33288c973"},
|
||||
{file = "simplejson-3.19.2-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:287e39ba24e141b046812c880f4619d0ca9e617235d74abc27267194fc0c7835"},
|
||||
{file = "simplejson-3.19.2-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:6f0a0b41dd05eefab547576bed0cf066595f3b20b083956b1405a6f17d1be6ad"},
|
||||
{file = "simplejson-3.19.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:2f98d918f7f3aaf4b91f2b08c0c92b1774aea113334f7cde4fe40e777114dbe6"},
|
||||
{file = "simplejson-3.19.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7d74beca677623481810c7052926365d5f07393c72cbf62d6cce29991b676402"},
|
||||
{file = "simplejson-3.19.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:7f2398361508c560d0bf1773af19e9fe644e218f2a814a02210ac2c97ad70db0"},
|
||||
{file = "simplejson-3.19.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ad331349b0b9ca6da86064a3599c425c7a21cd41616e175ddba0866da32df48"},
|
||||
{file = "simplejson-3.19.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:332c848f02d71a649272b3f1feccacb7e4f7e6de4a2e6dc70a32645326f3d428"},
|
||||
{file = "simplejson-3.19.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:25785d038281cd106c0d91a68b9930049b6464288cea59ba95b35ee37c2d23a5"},
|
||||
{file = "simplejson-3.19.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18955c1da6fc39d957adfa346f75226246b6569e096ac9e40f67d102278c3bcb"},
|
||||
{file = "simplejson-3.19.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:11cc3afd8160d44582543838b7e4f9aa5e97865322844b75d51bf4e0e413bb3e"},
|
||||
{file = "simplejson-3.19.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:b01fda3e95d07a6148702a641e5e293b6da7863f8bc9b967f62db9461330562c"},
|
||||
{file = "simplejson-3.19.2-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:778331444917108fa8441f59af45886270d33ce8a23bfc4f9b192c0b2ecef1b3"},
|
||||
{file = "simplejson-3.19.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:9eb117db8d7ed733a7317c4215c35993b815bf6aeab67523f1f11e108c040672"},
|
||||
{file = "simplejson-3.19.2-cp310-cp310-win32.whl", hash = "sha256:39b6d79f5cbfa3eb63a869639cfacf7c41d753c64f7801efc72692c1b2637ac7"},
|
||||
{file = "simplejson-3.19.2-cp310-cp310-win_amd64.whl", hash = "sha256:5675e9d8eeef0aa06093c1ff898413ade042d73dc920a03e8cea2fb68f62445a"},
|
||||
{file = "simplejson-3.19.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:ed628c1431100b0b65387419551e822987396bee3c088a15d68446d92f554e0c"},
|
||||
{file = "simplejson-3.19.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:adcb3332979cbc941b8fff07181f06d2b608625edc0a4d8bc3ffc0be414ad0c4"},
|
||||
{file = "simplejson-3.19.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:08889f2f597ae965284d7b52a5c3928653a9406d88c93e3161180f0abc2433ba"},
|
||||
{file = "simplejson-3.19.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ef7938a78447174e2616be223f496ddccdbf7854f7bf2ce716dbccd958cc7d13"},
|
||||
{file = "simplejson-3.19.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a970a2e6d5281d56cacf3dc82081c95c1f4da5a559e52469287457811db6a79b"},
|
||||
{file = "simplejson-3.19.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:554313db34d63eac3b3f42986aa9efddd1a481169c12b7be1e7512edebff8eaf"},
|
||||
{file = "simplejson-3.19.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d36081c0b1c12ea0ed62c202046dca11438bee48dd5240b7c8de8da62c620e9"},
|
||||
{file = "simplejson-3.19.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a3cd18e03b0ee54ea4319cdcce48357719ea487b53f92a469ba8ca8e39df285e"},
|
||||
{file = "simplejson-3.19.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:66e5dc13bfb17cd6ee764fc96ccafd6e405daa846a42baab81f4c60e15650414"},
|
||||
{file = "simplejson-3.19.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:972a7833d4a1fcf7a711c939e315721a88b988553fc770a5b6a5a64bd6ebeba3"},
|
||||
{file = "simplejson-3.19.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3e74355cb47e0cd399ead3477e29e2f50e1540952c22fb3504dda0184fc9819f"},
|
||||
{file = "simplejson-3.19.2-cp311-cp311-win32.whl", hash = "sha256:1dd4f692304854352c3e396e9b5f0a9c9e666868dd0bdc784e2ac4c93092d87b"},
|
||||
{file = "simplejson-3.19.2-cp311-cp311-win_amd64.whl", hash = "sha256:9300aee2a8b5992d0f4293d88deb59c218989833e3396c824b69ba330d04a589"},
|
||||
{file = "simplejson-3.19.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:b8d940fd28eb34a7084877747a60873956893e377f15a32ad445fe66c972c3b8"},
|
||||
{file = "simplejson-3.19.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:4969d974d9db826a2c07671273e6b27bc48e940738d768fa8f33b577f0978378"},
|
||||
{file = "simplejson-3.19.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c594642d6b13d225e10df5c16ee15b3398e21a35ecd6aee824f107a625690374"},
|
||||
{file = "simplejson-3.19.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2f5a398b5e77bb01b23d92872255e1bcb3c0c719a3be40b8df146570fe7781a"},
|
||||
{file = "simplejson-3.19.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:176a1b524a3bd3314ed47029a86d02d5a95cc0bee15bd3063a1e1ec62b947de6"},
|
||||
{file = "simplejson-3.19.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3c7363a8cb8c5238878ec96c5eb0fc5ca2cb11fc0c7d2379863d342c6ee367a"},
|
||||
{file = "simplejson-3.19.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:346820ae96aa90c7d52653539a57766f10f33dd4be609206c001432b59ddf89f"},
|
||||
{file = "simplejson-3.19.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:de9a2792612ec6def556d1dc621fd6b2073aff015d64fba9f3e53349ad292734"},
|
||||
{file = "simplejson-3.19.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:1c768e7584c45094dca4b334af361e43b0aaa4844c04945ac7d43379eeda9bc2"},
|
||||
{file = "simplejson-3.19.2-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:9652e59c022e62a5b58a6f9948b104e5bb96d3b06940c6482588176f40f4914b"},
|
||||
{file = "simplejson-3.19.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:9c1a4393242e321e344213a90a1e3bf35d2f624aa8b8f6174d43e3c6b0e8f6eb"},
|
||||
{file = "simplejson-3.19.2-cp312-cp312-win32.whl", hash = "sha256:7cb98be113911cb0ad09e5523d0e2a926c09a465c9abb0784c9269efe4f95917"},
|
||||
{file = "simplejson-3.19.2-cp312-cp312-win_amd64.whl", hash = "sha256:6779105d2fcb7fcf794a6a2a233787f6bbd4731227333a072d8513b252ed374f"},
|
||||
{file = "simplejson-3.19.2-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:061e81ea2d62671fa9dea2c2bfbc1eec2617ae7651e366c7b4a2baf0a8c72cae"},
|
||||
{file = "simplejson-3.19.2-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4280e460e51f86ad76dc456acdbfa9513bdf329556ffc8c49e0200878ca57816"},
|
||||
{file = "simplejson-3.19.2-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:11c39fbc4280d7420684494373b7c5904fa72a2b48ef543a56c2d412999c9e5d"},
|
||||
{file = "simplejson-3.19.2-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bccb3e88ec26ffa90f72229f983d3a5d1155e41a1171190fa723d4135523585b"},
|
||||
{file = "simplejson-3.19.2-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bb5b50dc6dd671eb46a605a3e2eb98deb4a9af787a08fcdddabe5d824bb9664"},
|
||||
{file = "simplejson-3.19.2-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:d94245caa3c61f760c4ce4953cfa76e7739b6f2cbfc94cc46fff6c050c2390c5"},
|
||||
{file = "simplejson-3.19.2-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:d0e5ffc763678d48ecc8da836f2ae2dd1b6eb2d27a48671066f91694e575173c"},
|
||||
{file = "simplejson-3.19.2-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:d222a9ed082cd9f38b58923775152003765016342a12f08f8c123bf893461f28"},
|
||||
{file = "simplejson-3.19.2-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:8434dcdd347459f9fd9c526117c01fe7ca7b016b6008dddc3c13471098f4f0dc"},
|
||||
{file = "simplejson-3.19.2-cp36-cp36m-win32.whl", hash = "sha256:c9ac1c2678abf9270e7228133e5b77c6c3c930ad33a3c1dfbdd76ff2c33b7b50"},
|
||||
{file = "simplejson-3.19.2-cp36-cp36m-win_amd64.whl", hash = "sha256:92c4a4a2b1f4846cd4364855cbac83efc48ff5a7d7c06ba014c792dd96483f6f"},
|
||||
{file = "simplejson-3.19.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0d551dc931638e2102b8549836a1632e6e7cf620af3d093a7456aa642bff601d"},
|
||||
{file = "simplejson-3.19.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:73a8a4653f2e809049999d63530180d7b5a344b23a793502413ad1ecea9a0290"},
|
||||
{file = "simplejson-3.19.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:40847f617287a38623507d08cbcb75d51cf9d4f9551dd6321df40215128325a3"},
|
||||
{file = "simplejson-3.19.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be893258d5b68dd3a8cba8deb35dc6411db844a9d35268a8d3793b9d9a256f80"},
|
||||
{file = "simplejson-3.19.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9eb3cff1b7d71aa50c89a0536f469cb8d6dcdd585d8f14fb8500d822f3bdee4"},
|
||||
{file = "simplejson-3.19.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d0f402e787e6e7ee7876c8b05e2fe6464820d9f35ba3f172e95b5f8b699f6c7f"},
|
||||
{file = "simplejson-3.19.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:fbbcc6b0639aa09b9649f36f1bcb347b19403fe44109948392fbb5ea69e48c3e"},
|
||||
{file = "simplejson-3.19.2-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:2fc697be37585eded0c8581c4788fcfac0e3f84ca635b73a5bf360e28c8ea1a2"},
|
||||
{file = "simplejson-3.19.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:0b0a3eb6dd39cce23801a50c01a0976971498da49bc8a0590ce311492b82c44b"},
|
||||
{file = "simplejson-3.19.2-cp37-cp37m-win32.whl", hash = "sha256:49f9da0d6cd17b600a178439d7d2d57c5ef01f816b1e0e875e8e8b3b42db2693"},
|
||||
{file = "simplejson-3.19.2-cp37-cp37m-win_amd64.whl", hash = "sha256:c87c22bd6a987aca976e3d3e23806d17f65426191db36d40da4ae16a6a494cbc"},
|
||||
{file = "simplejson-3.19.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:9e4c166f743bb42c5fcc60760fb1c3623e8fda94f6619534217b083e08644b46"},
|
||||
{file = "simplejson-3.19.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0a48679310e1dd5c9f03481799311a65d343748fe86850b7fb41df4e2c00c087"},
|
||||
{file = "simplejson-3.19.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:c0521e0f07cb56415fdb3aae0bbd8701eb31a9dfef47bb57206075a0584ab2a2"},
|
||||
{file = "simplejson-3.19.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d2d5119b1d7a1ed286b8af37357116072fc96700bce3bec5bb81b2e7057ab41"},
|
||||
{file = "simplejson-3.19.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2c1467d939932901a97ba4f979e8f2642415fcf02ea12f53a4e3206c9c03bc17"},
|
||||
{file = "simplejson-3.19.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:49aaf4546f6023c44d7e7136be84a03a4237f0b2b5fb2b17c3e3770a758fc1a0"},
|
||||
{file = "simplejson-3.19.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60848ab779195b72382841fc3fa4f71698a98d9589b0a081a9399904487b5832"},
|
||||
{file = "simplejson-3.19.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:0436a70d8eb42bea4fe1a1c32d371d9bb3b62c637969cb33970ad624d5a3336a"},
|
||||
{file = "simplejson-3.19.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:49e0e3faf3070abdf71a5c80a97c1afc059b4f45a5aa62de0c2ca0444b51669b"},
|
||||
{file = "simplejson-3.19.2-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ff836cd4041e16003549449cc0a5e372f6b6f871eb89007ab0ee18fb2800fded"},
|
||||
{file = "simplejson-3.19.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:3848427b65e31bea2c11f521b6fc7a3145d6e501a1038529da2391aff5970f2f"},
|
||||
{file = "simplejson-3.19.2-cp38-cp38-win32.whl", hash = "sha256:3f39bb1f6e620f3e158c8b2eaf1b3e3e54408baca96a02fe891794705e788637"},
|
||||
{file = "simplejson-3.19.2-cp38-cp38-win_amd64.whl", hash = "sha256:0405984f3ec1d3f8777c4adc33eac7ab7a3e629f3b1c05fdded63acc7cf01137"},
|
||||
{file = "simplejson-3.19.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:445a96543948c011a3a47c8e0f9d61e9785df2544ea5be5ab3bc2be4bd8a2565"},
|
||||
{file = "simplejson-3.19.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4a8c3cc4f9dfc33220246760358c8265dad6e1104f25f0077bbca692d616d358"},
|
||||
{file = "simplejson-3.19.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:af9c7e6669c4d0ad7362f79cb2ab6784d71147503e62b57e3d95c4a0f222c01c"},
|
||||
{file = "simplejson-3.19.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:064300a4ea17d1cd9ea1706aa0590dcb3be81112aac30233823ee494f02cb78a"},
|
||||
{file = "simplejson-3.19.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9453419ea2ab9b21d925d0fd7e3a132a178a191881fab4169b6f96e118cc25bb"},
|
||||
{file = "simplejson-3.19.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e038c615b3906df4c3be8db16b3e24821d26c55177638ea47b3f8f73615111c"},
|
||||
{file = "simplejson-3.19.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:16ca9c90da4b1f50f089e14485db8c20cbfff2d55424062791a7392b5a9b3ff9"},
|
||||
{file = "simplejson-3.19.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:1018bd0d70ce85f165185d2227c71e3b1e446186f9fa9f971b69eee223e1e3cd"},
|
||||
{file = "simplejson-3.19.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:e8dd53a8706b15bc0e34f00e6150fbefb35d2fd9235d095b4f83b3c5ed4fa11d"},
|
||||
{file = "simplejson-3.19.2-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:2d022b14d7758bfb98405672953fe5c202ea8a9ccf9f6713c5bd0718eba286fd"},
|
||||
{file = "simplejson-3.19.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:febffa5b1eda6622d44b245b0685aff6fb555ce0ed734e2d7b1c3acd018a2cff"},
|
||||
{file = "simplejson-3.19.2-cp39-cp39-win32.whl", hash = "sha256:4edcd0bf70087b244ba77038db23cd98a1ace2f91b4a3ecef22036314d77ac23"},
|
||||
{file = "simplejson-3.19.2-cp39-cp39-win_amd64.whl", hash = "sha256:aad7405c033d32c751d98d3a65801e2797ae77fac284a539f6c3a3e13005edc4"},
|
||||
{file = "simplejson-3.19.2-py3-none-any.whl", hash = "sha256:bcedf4cae0d47839fee7de344f96b5694ca53c786f28b5f773d4f0b265a159eb"},
|
||||
{file = "simplejson-3.19.2.tar.gz", hash = "sha256:9eb442a2442ce417801c912df68e1f6ccfcd41577ae7274953ab3ad24ef7d82c"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "six"
|
||||
version = "1.16.0"
|
||||
description = "Python 2 and 3 compatibility utilities"
|
||||
optional = false
|
||||
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*"
|
||||
files = [
|
||||
{file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"},
|
||||
{file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "stix2"
|
||||
version = "3.0.1"
|
||||
description = "Produce and consume STIX 2 JSON content"
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "stix2-3.0.1-py2.py3-none-any.whl", hash = "sha256:827acf0b5b319c1b857c9db0d54907bb438b2b32312d236c891a305ad49b0ba2"},
|
||||
{file = "stix2-3.0.1.tar.gz", hash = "sha256:2a2718dc3451c84c709990b2ca220cc39c75ed23e0864d7e8d8190a9365b0cbf"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
pytz = "*"
|
||||
requests = "*"
|
||||
simplejson = "*"
|
||||
stix2-patterns = ">=1.2.0"
|
||||
|
||||
[package.extras]
|
||||
semantic = ["haversine", "rapidfuzz"]
|
||||
taxii = ["taxii2-client (>=2.3.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "stix2-patterns"
|
||||
version = "2.0.0"
|
||||
description = "Validate STIX 2 Patterns."
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "stix2-patterns-2.0.0.tar.gz", hash = "sha256:07750c5a5af2c758e9d2aa4dde9d8e04bcd162ac2a9b0b4c4de4481d443efa08"},
|
||||
{file = "stix2_patterns-2.0.0-py2.py3-none-any.whl", hash = "sha256:ca4d68b2db42ed99794a418388769d2676ca828e9cac0b8629e73cd3f68f6458"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
antlr4-python3-runtime = ">=4.9.0,<4.10.0"
|
||||
six = "*"
|
||||
|
||||
[package.extras]
|
||||
dev = ["bumpversion", "check-manifest", "coverage", "pre-commit", "pytest", "pytest-cov", "sphinx", "sphinx-prompt", "tox"]
|
||||
docs = ["sphinx", "sphinx-prompt"]
|
||||
test = ["coverage", "pytest", "pytest-cov"]
|
||||
|
||||
[[package]]
|
||||
name = "tomli"
|
||||
version = "2.0.1"
|
||||
description = "A lil' TOML parser"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"},
|
||||
{file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typer"
|
||||
version = "0.9.0"
|
||||
description = "Typer, build great CLIs. Easy to code. Based on Python type hints."
|
||||
optional = false
|
||||
python-versions = ">=3.6"
|
||||
files = [
|
||||
{file = "typer-0.9.0-py3-none-any.whl", hash = "sha256:5d96d986a21493606a358cae4461bd8cdf83cbf33a5aa950ae629ca3b51467ee"},
|
||||
{file = "typer-0.9.0.tar.gz", hash = "sha256:50922fd79aea2f4751a8e0408ff10d2662bd0c8bbfa84755a699f3bada2978b2"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
click = ">=7.1.1,<9.0.0"
|
||||
typing-extensions = ">=3.7.4.3"
|
||||
|
||||
[package.extras]
|
||||
all = ["colorama (>=0.4.3,<0.5.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
|
||||
dev = ["autoflake (>=1.3.1,<2.0.0)", "flake8 (>=3.8.3,<4.0.0)", "pre-commit (>=2.17.0,<3.0.0)"]
|
||||
doc = ["cairosvg (>=2.5.2,<3.0.0)", "mdx-include (>=1.4.1,<2.0.0)", "mkdocs (>=1.1.2,<2.0.0)", "mkdocs-material (>=8.1.4,<9.0.0)", "pillow (>=9.3.0,<10.0.0)"]
|
||||
test = ["black (>=22.3.0,<23.0.0)", "coverage (>=6.2,<7.0)", "isort (>=5.0.6,<6.0.0)", "mypy (==0.910)", "pytest (>=4.4.0,<8.0.0)", "pytest-cov (>=2.10.0,<5.0.0)", "pytest-sugar (>=0.9.4,<0.10.0)", "pytest-xdist (>=1.32.0,<4.0.0)", "rich (>=10.11.0,<14.0.0)", "shellingham (>=1.3.0,<2.0.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "typing-extensions"
|
||||
version = "4.8.0"
|
||||
description = "Backported and Experimental Type Hints for Python 3.8+"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "typing_extensions-4.8.0-py3-none-any.whl", hash = "sha256:8f92fc8806f9a6b641eaa5318da32b44d401efaac0f6678c9bc448ba3605faa0"},
|
||||
{file = "typing_extensions-4.8.0.tar.gz", hash = "sha256:df8e4339e9cb77357558cbdbceca33c303714cf861d1eef15e1070055ae8b7ef"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "urllib3"
|
||||
version = "2.1.0"
|
||||
description = "HTTP library with thread-safe connection pooling, file post, and more."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "urllib3-2.1.0-py3-none-any.whl", hash = "sha256:55901e917a5896a349ff771be919f8bd99aff50b79fe58fec595eb37bbc56bb3"},
|
||||
{file = "urllib3-2.1.0.tar.gz", hash = "sha256:df7aa8afb0148fa78488e7899b2c59b5f4ffcfa82e6c54ccb9dd37c1d7b52d54"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)"]
|
||||
socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"]
|
||||
zstd = ["zstandard (>=0.18.0)"]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = "^3.10"
|
||||
content-hash = "adbf41d469cd7b6a5e736194fa484063e644a43ffb2426173931336e3ae0bf64"
|
|
@ -0,0 +1,27 @@
|
|||
[tool.poetry]
|
||||
name = "falco_mitre_attack_checker"
|
||||
version = "0.1.0"
|
||||
description = "Audit module to validate Falco rules against the Mitre ATT&CK Framework"
|
||||
authors = ["The Falco Authors <cncf-falco-dev@lists.cncf.io>"]
|
||||
license = "Apache-2.0"
|
||||
readme = "README.md"
|
||||
packages = [{include = "falco_mitre_attack_checker"}]
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = "^3.10"
|
||||
pydantic = "^1.10.9"
|
||||
stix2 = "^3.0.1"
|
||||
typer = "^0.9.0"
|
||||
pyyaml = "^6.0"
|
||||
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
pytest-cov = "^4.1.0"
|
||||
pytest = "^7.4.0"
|
||||
safety = "^2.3.5"
|
||||
|
||||
[build-system]
|
||||
requires = ["poetry-core"]
|
||||
build-backend = "poetry.core.masonry.api"
|
||||
|
||||
[tool.poetry.scripts]
|
||||
falco_mitre_attack_checker = "mitre_attack_checker.__main__:main"
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
|
@ -192,9 +193,24 @@ func doPushToOCI(registryFilename, gitTag string) (*string, error) {
|
|||
}
|
||||
|
||||
func rulesOciRepos(registryEntries *Registry, ociRepoPrefix string) (map[string]string, error) {
|
||||
var user, token string
|
||||
var repo *repository.Repository
|
||||
var err error
|
||||
ociClient := authn.NewClient(authn.WithCredentials(&auth.EmptyCredential))
|
||||
var foundUser, foundToken bool
|
||||
var cred *auth.Credential
|
||||
|
||||
user, foundUser = os.LookupEnv(RegistryUserEnv)
|
||||
token, foundToken = os.LookupEnv(RegistryTokenEnv)
|
||||
|
||||
if !foundUser && !foundToken {
|
||||
cred = &auth.EmptyCredential
|
||||
} else {
|
||||
cred = &auth.Credential{
|
||||
Username: user,
|
||||
Password: token,
|
||||
}
|
||||
}
|
||||
ociClient := authn.NewClient(authn.WithCredentials(cred))
|
||||
ociEntries := make(map[string]string)
|
||||
|
||||
for _, entry := range registryEntries.Rulesfiles {
|
||||
|
@ -254,7 +270,7 @@ func main() {
|
|||
|
||||
updateIndexCmd := &cobra.Command{
|
||||
Use: "update-index <registryFilename> <indexFilename>",
|
||||
Short: "Update an index file for artifacts distribution using registry data",
|
||||
Short: "Update an index file for artifacts distribution using registry data, authenticates to the registry if REGISTRY_USER, REGISTRY_TOKEN are set",
|
||||
Args: cobra.ExactArgs(2),
|
||||
DisableFlagsInUseLine: true,
|
||||
RunE: func(c *cobra.Command, args []string) error {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
|
@ -30,7 +31,7 @@ import (
|
|||
|
||||
const (
|
||||
rulesEngineAnchor = "- required_engine_version"
|
||||
engineVersionKey = "engine_version"
|
||||
engineVersionKey = "engine_version_semver"
|
||||
)
|
||||
|
||||
// ErrReqNotFound error when the requirements are not found in the rulesfile.
|
||||
|
@ -64,13 +65,23 @@ func rulesfileRequirement(filePath string) (*oci.ArtifactRequirement, error) {
|
|||
|
||||
// Split the requirement and parse the version to semVer.
|
||||
tokens := strings.Split(fileScanner.Text(), ":")
|
||||
reqVer, err := semver.ParseTolerant(tokens[1])
|
||||
version := strings.TrimSpace(tokens[1])
|
||||
reqVer, err := semver.Parse(version)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse to semVer the version requirement %q", tokens[1])
|
||||
// If the version is not a valid semver, we try to parse it as a numeric value.
|
||||
minor, err := strconv.ParseUint(version, 10, 64)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse requirement %q: expected a numeric value or a valid semver string", version)
|
||||
}
|
||||
reqVer = semver.Version{
|
||||
Major: 0,
|
||||
Minor: minor,
|
||||
Patch: 0,
|
||||
}
|
||||
}
|
||||
|
||||
return &oci.ArtifactRequirement{
|
||||
Name: engineVersionKey,
|
||||
Version: strconv.FormatUint(reqVer.Major, 10),
|
||||
Version: reqVer.String(),
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2024 The Falco Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRulesFilesRequirement(t *testing.T) {
|
||||
req, err := rulesfileRequirement("testdata/rules-failed-req.yaml")
|
||||
assert.Error(t, err)
|
||||
|
||||
req, err = rulesfileRequirement("testdata/rules-numeric-req.yaml")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "0.15.0", req.Version)
|
||||
assert.Equal(t, "engine_version_semver", req.Name)
|
||||
|
||||
req, err = rulesfileRequirement("testdata/rules-semver-req.yaml")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "0.31.0", req.Version)
|
||||
assert.Equal(t, "engine_version_semver", req.Name)
|
||||
}
|
|
@ -1,3 +1,20 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
// SPDX-License-Identifier: Apache-2.0
|
||||
/*
|
||||
Copyright (C) 2023 The Falco Authors.
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
- required_engine_version: test
|
|
@ -0,0 +1 @@
|
|||
- required_engine_version: 15
|
|
@ -0,0 +1 @@
|
|||
- required_engine_version: 0.31.0
|
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
Binary file not shown.
After Width: | Height: | Size: 6.0 KiB |
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
After Width: | Height: | Size: 15 KiB |
|
@ -1,3 +1,4 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2023 The Falco Authors.
|
||||
#
|
||||
|
@ -26,6 +27,10 @@ rulesfiles:
|
|||
path: rules/falco_rules.yaml
|
||||
license: apache-2.0
|
||||
url: https://github.com/falcosecurity/rules/blob/main/rules/falco_rules.yaml
|
||||
signature:
|
||||
cosign:
|
||||
certificate-oidc-issuer: https://token.actions.githubusercontent.com
|
||||
certificate-identity-regexp: https://github.com/falcosecurity/rules/
|
||||
- name: falco-incubating-rules
|
||||
description: Falco incubating rules
|
||||
authors: The Falco Authors
|
||||
|
@ -36,6 +41,10 @@ rulesfiles:
|
|||
path: rules/falco-incubating_rules.yaml
|
||||
license: apache-2.0
|
||||
url: https://github.com/falcosecurity/rules/blob/main/rules/falco-incubating_rules.yaml
|
||||
signature:
|
||||
cosign:
|
||||
certificate-oidc-issuer: https://token.actions.githubusercontent.com
|
||||
certificate-identity-regexp: https://github.com/falcosecurity/rules/
|
||||
- name: falco-sandbox-rules
|
||||
description: Falco sandbox rules
|
||||
authors: The Falco Authors
|
||||
|
@ -46,6 +55,10 @@ rulesfiles:
|
|||
path: rules/falco-sandbox_rules.yaml
|
||||
license: apache-2.0
|
||||
url: https://github.com/falcosecurity/rules/blob/main/rules/falco-sandbox_rules.yaml
|
||||
signature:
|
||||
cosign:
|
||||
certificate-oidc-issuer: https://token.actions.githubusercontent.com
|
||||
certificate-identity-regexp: https://github.com/falcosecurity/rules/
|
||||
- name: falco-deprecated-rules
|
||||
description: Falco deprecated rules kept as examples but are no longer maintained
|
||||
authors: The Falco Authors
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
approvers:
|
||||
- darryk10
|
||||
- loresuso
|
|
@ -1,5 +1,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2023 The Falco Authors.
|
||||
# Copyright (C) 2025 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -24,7 +25,11 @@
|
|||
|
||||
# Starting with version 8, the Falco engine supports exceptions.
|
||||
# However the Falco rules file does not use them by default.
|
||||
- required_engine_version: 17
|
||||
- required_engine_version: 0.50.0
|
||||
|
||||
- required_plugin_versions:
|
||||
- name: container
|
||||
version: 0.2.2
|
||||
|
||||
# This macro `never_true` is used as placeholder for tuning negative logical sub-expressions, for example
|
||||
# - macro: allowed_ssh_hosts
|
||||
|
@ -86,7 +91,7 @@
|
|||
and ssh_port
|
||||
and not allowed_ssh_hosts
|
||||
enabled: false
|
||||
output: Disallowed SSH Connection (connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Disallowed SSH Connection | connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_deprecated, host, container, network, mitre_lateral_movement, T1021.004]
|
||||
|
||||
|
@ -120,16 +125,11 @@
|
|||
(fd.snet in (allowed_outbound_destination_networks)) or
|
||||
(fd.sip.name in (allowed_outbound_destination_domains)))
|
||||
enabled: false
|
||||
output: Disallowed outbound connection destination (connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Disallowed outbound connection destination | connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_deprecated, host, container, network, mitre_command_and_control, TA0011]
|
||||
|
||||
# Use this to test whether the event occurred within a container.
|
||||
# When displaying container information in the output field, use
|
||||
# %container.info, without any leading term (file=%fd.name
|
||||
# %container.info user=%user.name user_loginuid=%user.loginuid, and not file=%fd.name
|
||||
# container=%container.info user=%user.name user_loginuid=%user.loginuid). The output will change
|
||||
# based on the context and whether or not -pk/-pm/-pc was specified on
|
||||
# the command line.
|
||||
- macro: container
|
||||
condition: (container.id != host)
|
||||
|
||||
|
@ -168,7 +168,7 @@
|
|||
and not proc.name in (authorized_server_binary)
|
||||
and not fd.sport in (authorized_server_port)
|
||||
enabled: false
|
||||
output: Network connection outside authorized port and binary (connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Network connection outside authorized port and binary | connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: WARNING
|
||||
tags: [maturity_deprecated, container, network, mitre_discovery, TA0011, NIST_800-53_CM-7]
|
||||
|
||||
|
@ -189,7 +189,7 @@
|
|||
outbound
|
||||
and ((fd.sip in (c2_server_ip_list)) or
|
||||
(fd.sip.name in (c2_server_fqdn_list)))
|
||||
output: Outbound connection to C2 server (c2_domain=%fd.sip.name c2_addr=%fd.sip connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Outbound connection to C2 server | c2_domain=%fd.sip.name c2_addr=%fd.sip connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: WARNING
|
||||
enabled: false
|
||||
tags: [maturity_deprecated, host, container, network, mitre_command_and_control, TA0011]
|
||||
tags: [maturity_deprecated, host, container, network, mitre_command_and_control, TA0011]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2023 The Falco Authors.
|
||||
# Copyright (C) 2025 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -24,7 +25,11 @@
|
|||
|
||||
# Starting with version 8, the Falco engine supports exceptions.
|
||||
# However the Falco rules file does not use them by default.
|
||||
- required_engine_version: 26
|
||||
- required_engine_version: 0.50.0
|
||||
|
||||
- required_plugin_versions:
|
||||
- name: container
|
||||
version: 0.2.2
|
||||
|
||||
- macro: open_write
|
||||
condition: (evt.type in (open,openat,openat2) and evt.is_open_write=true and fd.typechar='f' and fd.num>=0)
|
||||
|
@ -62,7 +67,7 @@
|
|||
# on the identity of the process performing an action such as opening
|
||||
# a file, etc., we require that the process name be known.
|
||||
- macro: proc_name_exists
|
||||
condition: (proc.name!="<NA>")
|
||||
condition: (not proc.name in ("<NA>","N/A"))
|
||||
|
||||
- macro: rename
|
||||
condition: (evt.type in (rename, renameat, renameat2))
|
||||
|
@ -264,7 +269,7 @@
|
|||
and not proc.name in (shell_binaries)
|
||||
and not exe_running_docker_save
|
||||
and not user_known_shell_config_modifiers
|
||||
output: A shell configuration file has been modified (file=%fd.name pcmdline=%proc.pcmdline evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: A shell configuration file has been modified | file=%fd.name pcmdline=%proc.pcmdline evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority:
|
||||
WARNING
|
||||
tags: [maturity_incubating, host, container, filesystem, mitre_persistence, T1546.004]
|
||||
|
@ -280,27 +285,18 @@
|
|||
((open_write and fd.name startswith /etc/cron) or
|
||||
(spawned_process and proc.name = "crontab"))
|
||||
and not user_known_cron_jobs
|
||||
output: Cron jobs were scheduled to run (file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Cron jobs were scheduled to run | file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority:
|
||||
NOTICE
|
||||
tags: [maturity_incubating, host, container, filesystem, mitre_execution, T1053.003]
|
||||
|
||||
# Use this to test whether the event occurred within a container.
|
||||
#
|
||||
# When displaying container information in the output field, use
|
||||
# %container.info, without any leading term (file=%fd.name
|
||||
# %container.info user=%user.name user_loginuid=%user.loginuid, and not file=%fd.name
|
||||
# container=%container.info user=%user.name user_loginuid=%user.loginuid). The output will change
|
||||
# based on the context and whether or not -pk/-pm/-pc was specified on
|
||||
# the command line.
|
||||
- macro: container
|
||||
condition: (container.id != host)
|
||||
|
||||
- macro: container_started
|
||||
condition: >
|
||||
((evt.type = container or
|
||||
(spawned_process and proc.vpid=1)) and
|
||||
container.image.repository != incomplete)
|
||||
(spawned_process and proc.vpid=1 and container)
|
||||
|
||||
- list: cron_binaries
|
||||
items: [anacron, cron, crond, crontab]
|
||||
|
@ -376,7 +372,7 @@
|
|||
and (user_ssh_directory or fd.name startswith /root/.ssh)
|
||||
and not user_known_read_ssh_information_activities
|
||||
and not proc.name in (ssh_binaries)
|
||||
output: ssh-related file/directory read by non-ssh program (file=%fd.name pcmdline=%proc.pcmdline evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: ssh-related file/directory read by non-ssh program | file=%fd.name pcmdline=%proc.pcmdline evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: ERROR
|
||||
tags: [maturity_incubating, host, container, filesystem, mitre_collection, T1005]
|
||||
|
||||
|
@ -400,7 +396,7 @@
|
|||
and not proc.name in (db_server_binaries)
|
||||
and not postgres_running_wal_e
|
||||
and not user_known_db_spawned_processes
|
||||
output: Database-related program spawned process other than itself (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Database-related program spawned process other than itself | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: NOTICE
|
||||
tags: [maturity_incubating, host, container, process, database, mitre_execution, T1190]
|
||||
|
||||
|
@ -441,7 +437,7 @@
|
|||
and not calico_node
|
||||
and not weaveworks_scope
|
||||
and not user_known_change_thread_namespace_activities
|
||||
output: Namespace change (setns) by unexpected program (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Namespace change (setns) by unexpected program | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_incubating, host, container, process, mitre_privilege_escalation, T1611]
|
||||
|
||||
|
@ -455,7 +451,7 @@
|
|||
evt.type=unshare and evt.dir=<
|
||||
and container
|
||||
and not thread.cap_permitted contains CAP_SYS_ADMIN
|
||||
output: Change namespace privileges via unshare (res=%evt.res evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Change namespace privileges via unshare | res=%evt.res evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_incubating, container, mitre_privilege_escalation, T1611]
|
||||
|
||||
|
@ -558,7 +554,6 @@
|
|||
- public.ecr.aws/falcosecurity/falco-no-driver
|
||||
|
||||
# These container images are allowed to run with --privileged and full set of capabilities
|
||||
# TODO: Remove k8s.gcr.io reference after 01/Dec/2023
|
||||
- list: falco_privileged_images
|
||||
items: [
|
||||
falco_containers,
|
||||
|
@ -577,16 +572,12 @@
|
|||
gke.gcr.io/netd-amd64,
|
||||
gke.gcr.io/watcher-daemonset,
|
||||
gcr.io/google-containers/prometheus-to-sd,
|
||||
k8s.gcr.io/ip-masq-agent-amd64,
|
||||
k8s.gcr.io/kube-proxy,
|
||||
k8s.gcr.io/prometheus-to-sd,
|
||||
registry.k8s.io/ip-masq-agent-amd64,
|
||||
registry.k8s.io/kube-proxy,
|
||||
registry.k8s.io/prometheus-to-sd,
|
||||
quay.io/calico/node,
|
||||
sysdig/sysdig,
|
||||
sematext_images,
|
||||
k8s.gcr.io/dns/k8s-dns-node-cache,
|
||||
registry.k8s.io/dns/k8s-dns-node-cache,
|
||||
mcr.microsoft.com/oss/kubernetes/kube-proxy
|
||||
]
|
||||
|
@ -617,12 +608,11 @@
|
|||
seen as more suspicious, prompting a closer inspection.
|
||||
condition: >
|
||||
container_started
|
||||
and container
|
||||
and container.privileged=true
|
||||
and not falco_privileged_containers
|
||||
and not user_privileged_containers
|
||||
and not redhat_image
|
||||
output: Privileged container started (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Privileged container started | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: INFO
|
||||
tags: [maturity_incubating, container, cis, mitre_execution, T1610, PCI_DSS_10.2.5]
|
||||
|
||||
|
@ -647,11 +637,10 @@
|
|||
raise suspicion, prompting closer scrutiny.
|
||||
condition: >
|
||||
container_started
|
||||
and container
|
||||
and excessively_capable_container
|
||||
and not falco_privileged_containers
|
||||
and not user_privileged_containers
|
||||
output: Excessively capable container started (cap_permitted=%thread.cap_permitted evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Excessively capable container started | cap_permitted=%thread.cap_permitted evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: INFO
|
||||
tags: [maturity_incubating, container, cis, mitre_execution, T1610]
|
||||
|
||||
|
@ -672,7 +661,7 @@
|
|||
and not proc.name in (known_system_procs_network_activity_binaries)
|
||||
and not login_doing_dns_lookup
|
||||
and not user_expected_system_procs_network_activity_conditions
|
||||
output: Known system binary sent/received network traffic (connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Known system binary sent/received network traffic | connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=%fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_incubating, host, network, process, mitre_execution, T1059]
|
||||
|
||||
|
@ -711,7 +700,7 @@
|
|||
and http_proxy_procs
|
||||
and proc.env icontains HTTP_PROXY
|
||||
and not allowed_ssh_proxy_env
|
||||
output: Curl or wget run with disallowed HTTP_PROXY environment variable (env=%proc.env evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Curl or wget run with disallowed HTTP_PROXY environment variable | env=%proc.env evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: NOTICE
|
||||
tags: [maturity_incubating, host, container, users, mitre_execution, T1204]
|
||||
|
||||
|
@ -751,7 +740,7 @@
|
|||
inbound_outbound
|
||||
and fd.l4proto=udp
|
||||
and not expected_udp_traffic
|
||||
output: Unexpected UDP Traffic Seen (connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Unexpected UDP Traffic Seen | connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=%fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_incubating, host, container, network, mitre_exfiltration, TA0011]
|
||||
|
||||
|
@ -773,7 +762,7 @@
|
|||
# https://github.com/draios/sysdig/issues/954). So in that case, allow
|
||||
# a setuid.
|
||||
- macro: known_user_in_container
|
||||
condition: (container and user.name != "N/A")
|
||||
condition: (container and not user.name in ("<NA>","N/A",""))
|
||||
|
||||
# Add conditions to this macro (probably in a separate file,
|
||||
# overwriting this macro) to allow for specific combinations of
|
||||
|
@ -803,7 +792,7 @@
|
|||
and not java_running_sdjagent
|
||||
and not nrpe_becoming_nagios
|
||||
and not user_known_non_sudo_setuid_conditions
|
||||
output: Unexpected setuid call by non-sudo, non-root program (arg_uid=%evt.arg.uid evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Unexpected setuid call by non-sudo, non-root program | arg_uid=%evt.arg.uid evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_incubating, host, container, users, mitre_privilege_escalation, T1548.001]
|
||||
|
||||
|
@ -835,7 +824,7 @@
|
|||
and not run_by_google_accounts_daemon
|
||||
and not chage_list
|
||||
and not user_known_user_management_activities
|
||||
output: User management binary command run outside of container (gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: User management binary command run outside of container | gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: NOTICE
|
||||
tags: [maturity_incubating, host, users, software_mgmt, mitre_persistence, T1098]
|
||||
|
||||
|
@ -863,7 +852,7 @@
|
|||
and not fd.name in (allowed_dev_files)
|
||||
and not fd.name startswith /dev/tty
|
||||
and not user_known_create_files_below_dev_activities
|
||||
output: File created below /dev by untrusted program (file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: File created below /dev by untrusted program | file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: ERROR
|
||||
tags: [maturity_incubating, host, filesystem, mitre_persistence, T1543]
|
||||
|
||||
|
@ -890,7 +879,7 @@
|
|||
and container
|
||||
and fd.sip="169.254.169.254"
|
||||
and not ec2_metadata_containers
|
||||
output: Outbound connection to EC2 instance metadata service (connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Outbound connection to EC2 instance metadata service | connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=%fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_incubating, network, aws, container, mitre_credential_access, T1552.005]
|
||||
|
||||
|
@ -911,7 +900,7 @@
|
|||
and fd.sip="169.254.169.254"
|
||||
and not user_known_metadata_access
|
||||
enabled: true
|
||||
output: Outbound connection to cloud instance metadata service (connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Outbound connection to cloud instance metadata service | connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=%fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_incubating, network, container, mitre_discovery, T1565]
|
||||
|
||||
|
@ -931,12 +920,10 @@
|
|||
condition: (never_true)
|
||||
|
||||
# Container is supposed to be immutable. Package management should be done in building the image.
|
||||
# TODO: Remove k8s.gcr.io reference after 01/Dec/2023
|
||||
- macro: pkg_mgmt_in_kube_proxy
|
||||
condition: >
|
||||
(proc.cmdline startswith "update-alternat"
|
||||
and (container.image.repository = "registry.k8s.io/kube-proxy"
|
||||
or container.image.repository = "k8s.gcr.io/kube-proxy"))
|
||||
and container.image.repository = "registry.k8s.io/kube-proxy")
|
||||
|
||||
- rule: Launch Package Management Process in Container
|
||||
desc: >
|
||||
|
@ -952,7 +939,7 @@
|
|||
and not package_mgmt_ancestor_procs
|
||||
and not user_known_package_manager_in_container
|
||||
and not pkg_mgmt_in_kube_proxy
|
||||
output: Package management process launched in container (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Package management process launched in container | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: ERROR
|
||||
tags: [maturity_incubating, container, process, software_mgmt, mitre_persistence, T1505]
|
||||
|
||||
|
@ -969,7 +956,7 @@
|
|||
and container
|
||||
and network_tool_procs
|
||||
and not user_known_network_tool_activities
|
||||
output: Network tool launched in container (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Network tool launched in container | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: NOTICE
|
||||
tags: [maturity_incubating, container, network, process, mitre_execution, T1059]
|
||||
|
||||
|
@ -983,7 +970,7 @@
|
|||
and not container
|
||||
and network_tool_procs
|
||||
and not user_known_network_tool_activities
|
||||
output: Network tool launched on host (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags)
|
||||
output: Network tool launched on host | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: NOTICE
|
||||
tags: [maturity_incubating, host, network, process, mitre_execution, T1059]
|
||||
|
||||
|
@ -1016,6 +1003,10 @@
|
|||
- macro: var_lib_docker_filepath
|
||||
condition: (evt.arg.name startswith /var/lib/docker or fd.name startswith /var/lib/docker)
|
||||
|
||||
# todo!: the usage of `evt.arg*` filter check in the output should be avoided
|
||||
# when more than one event type is involved because some event will populate
|
||||
# the filtercheck and others will always return <NA>. It would be better to use
|
||||
# a more generic filter like `fs.path.*`
|
||||
- rule: Delete or rename shell history
|
||||
desc: >
|
||||
Detect shell history deletion, frequently used by unsophisticated adversaries to eliminate evidence.
|
||||
|
@ -1025,7 +1016,7 @@
|
|||
(modify_shell_history or truncate_shell_history)
|
||||
and not var_lib_docker_filepath
|
||||
and not proc.name in (docker_binaries)
|
||||
output: Shell history deleted or renamed (file=%fd.name name=%evt.arg.name path=%evt.arg.path oldpath=%evt.arg.oldpath evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Shell history deleted or renamed | file=%fd.name name=%evt.arg.name path=%evt.arg.path oldpath=%evt.arg.oldpath evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority:
|
||||
WARNING
|
||||
tags: [maturity_incubating, host, container, process, filesystem, mitre_defense_evasion, T1070]
|
||||
|
@ -1039,6 +1030,11 @@
|
|||
- macro: user_known_set_setuid_or_setgid_bit_conditions
|
||||
condition: (never_true)
|
||||
|
||||
# todo!: the usage of `evt.arg*` filter check in the output should be avoided
|
||||
# when more than one event type is involved because some event will populate
|
||||
# the filtercheck and others will always return <NA>. In this specific
|
||||
# rule, 'chmod' doesn't have a `%evt.arg.fd` argument for example so
|
||||
# we will always return `<NA>`.
|
||||
- rule: Set Setuid or Setgid bit
|
||||
desc: >
|
||||
This rule is focused on detecting the use of setuid or setgid bits set via chmod. These bits, when set for an application,
|
||||
|
@ -1051,7 +1047,7 @@
|
|||
and not proc.name in (user_known_chmod_applications)
|
||||
and not exe_running_docker_save
|
||||
and not user_known_set_setuid_or_setgid_bit_conditions
|
||||
output: Setuid or setgid bit is set via chmod (fd=%evt.arg.fd filename=%evt.arg.filename mode=%evt.arg.mode evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Setuid or setgid bit is set via chmod | fd=%evt.arg.fd filename=%evt.arg.filename mode=%evt.arg.mode evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority:
|
||||
NOTICE
|
||||
tags: [maturity_incubating, host, container, process, users, mitre_privilege_escalation, T1548.001]
|
||||
|
@ -1076,7 +1072,7 @@
|
|||
and container
|
||||
and remote_file_copy_procs
|
||||
and not user_known_remote_file_copy_activities
|
||||
output: Remote file copy tool launched in container (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Remote file copy tool launched in container | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: NOTICE
|
||||
tags: [maturity_incubating, container, network, process, mitre_exfiltration, T1020]
|
||||
|
||||
|
@ -1106,7 +1102,7 @@
|
|||
and container
|
||||
and k8s.ns.name in (namespace_scope_network_only_subnet)
|
||||
and not network_local_subnet
|
||||
output: Network connection outside local subnet (fd_rip_name=%fd.rip.name fd_lip_name=%fd.lip.name fd_cip_name=%fd.cip.name fd_sip_name=%fd.sip.name connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Network connection outside local subnet | fd_rip_name=%fd.rip.name fd_lip_name=%fd.lip.name fd_cip_name=%fd.cip.name fd_sip_name=%fd.sip.name connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=%fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: WARNING
|
||||
tags: [maturity_incubating, container, network, mitre_discovery, T1046, PCI_DSS_6.4.2]
|
||||
|
||||
|
@ -1140,7 +1136,7 @@
|
|||
and not known_gke_mount_in_privileged_containers
|
||||
and not known_aks_mount_in_privileged_containers
|
||||
and not user_known_mount_in_privileged_containers
|
||||
output: Mount was executed inside a privileged container (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Mount was executed inside a privileged container | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: WARNING
|
||||
tags: [maturity_incubating, container, cis, filesystem, mitre_privilege_escalation, T1611]
|
||||
|
||||
|
@ -1172,7 +1168,7 @@
|
|||
and container
|
||||
and (ingress_remote_file_copy_procs or curl_download)
|
||||
and not user_known_ingress_remote_file_copy_activities
|
||||
output: Ingress remote file copy tool launched in container (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Ingress remote file copy tool launched in container | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: NOTICE
|
||||
tags: [maturity_incubating, container, network, process, mitre_command_and_control, TA0011]
|
||||
|
||||
|
@ -1193,7 +1189,7 @@
|
|||
and container
|
||||
and (fd.name glob /proc/*/environ)
|
||||
and not proc.name in (known_binaries_to_read_environment_variables_from_proc_files)
|
||||
output: Environment variables were retrieved from /proc files (file=%fd.name gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Environment variables were retrieved from /proc files | file=%fd.name gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: WARNING
|
||||
tags: [maturity_incubating, container, filesystem, process, mitre_discovery, T1083]
|
||||
|
||||
|
@ -1208,7 +1204,7 @@
|
|||
# We also let runc:[1:CHILD] count as the parent process, which can occur
|
||||
# when we lose events and lose track of state.
|
||||
- macro: container_entrypoint
|
||||
condition: (not proc.pname exists or proc.pname in (runc:[0:PARENT], runc:[1:CHILD], runc, docker-runc, exe, docker-runc-cur, containerd-shim, systemd, crio))
|
||||
condition: (not proc.pname exists or proc.pname in (runc:[0:PARENT], runc:[1:CHILD], runc, docker-runc, exe, docker-runc-cur, containerd-shim, systemd, crio, conmon))
|
||||
|
||||
- macro: system_level_side_effect_artifacts_kubectl_cp
|
||||
condition: (fd.name startswith /etc or
|
||||
|
@ -1232,6 +1228,73 @@
|
|||
and container_entrypoint
|
||||
and proc.tty=0
|
||||
and not system_level_side_effect_artifacts_kubectl_cp
|
||||
output: Exfiltrating Artifacts via Kubernetes Control Plane (file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Exfiltrating Artifacts via Kubernetes Control Plane | file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_incubating, container, filesystem, mitre_exfiltration, TA0010]
|
||||
|
||||
- rule: Adding ssh keys to authorized_keys
|
||||
desc: >
|
||||
After gaining access, attackers can modify the authorized_keys file to maintain persistence on a victim host.
|
||||
Where authorized_keys files are modified via cloud APIs or command line interfaces, an adversary may achieve
|
||||
privilege escalation on the target virtual machine if they add a key to a higher-privileged user.
|
||||
This rules aims at detecting any modification to the authorized_keys file, that is usually located under the .ssh
|
||||
directory in any user's home directory. This rule complements the more generic auditing rule "Read ssh information"
|
||||
by specifically detecting the writing of new, potentially attacker-provided keys.
|
||||
condition: >
|
||||
open_write
|
||||
and (user_ssh_directory or fd.name startswith /root/.ssh)
|
||||
and fd.name endswith authorized_keys
|
||||
and not proc.name in (ssh_binaries)
|
||||
output: Adding ssh keys to authorized_keys | file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: WARNING
|
||||
tags: [maturity_incubating, host, filesystem, mitre_persistence, T1098.004]
|
||||
|
||||
# possible use of CVE-2023-4911
|
||||
- macro: glibc_tunables_env
|
||||
condition: (proc.env icontains GLIBC_TUNABLES)
|
||||
|
||||
- rule: Potential Local Privilege Escalation via Environment Variables Misuse
|
||||
desc: >
|
||||
Process run with suspect environment variable that could be attempting privilege escalation. One use case is
|
||||
detecting the use of the GLIBC_TUNABLES environment variable, which could be used for privilege escalation
|
||||
on systems running vulnerable glibc versions. Only known and carefully profiled processes that legitimately
|
||||
exhibit this behavior should be excluded from this rule. This rule is expected to trigger on every attempt,
|
||||
even failed ones.
|
||||
condition: >
|
||||
spawned_process
|
||||
and glibc_tunables_env
|
||||
enabled: true
|
||||
output: Process run with suspect environment variable which could be attempting privilege escalation | env=%proc.env evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: NOTICE
|
||||
tags: [maturity_incubating, host, container, users, mitre_privilege_escalation, TA0004]
|
||||
|
||||
- rule: Backdoored library loaded into SSHD (CVE-2024-3094)
|
||||
desc: This rule detects possible CVE-2024-3094 exploitation when the SSH daemon process loads a vulnerable version of the liblzma library. An attacker could exploit this to interfere with authentication in sshd via systemd, potentially compromising sensitive data or escalating their privileges.
|
||||
condition: >
|
||||
open_read and
|
||||
proc.name=sshd and
|
||||
(fd.name contains "liblzma.so.5.6.0" or fd.name contains "liblzma.so.5.6.1")
|
||||
output: SSHD loaded a backdoored version of liblzma library %fd.name with parent %proc.pname and cmdline %proc.cmdline | process=%proc.name parent=%proc.pname file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid proc_exepath=%proc.exepath command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: WARNING
|
||||
tags: [maturity_incubating, host, container, mitre_initial_access, T1556]
|
||||
|
||||
- list: bpf_profiled_binaries
|
||||
items: [falco, bpftool, systemd]
|
||||
|
||||
- macro: bpf_profiled_procs
|
||||
condition: (proc.name in (bpf_profiled_binaries))
|
||||
|
||||
- rule: BPF Program Not Profiled
|
||||
desc: >
|
||||
BPF is a kernel technology that can be misused for malicious purposes, like "Linux Kernel Module Injection". This
|
||||
rule should be considered an auditing rule to notify you of any unprofiled BPF tools running in your environment.
|
||||
However, it requires customization after profiling your environment. BPF-powered agents make bpf syscalls all the
|
||||
time, so this rule only sends logs for BPF_PROG_LOAD calls (bpf cmd=5) in the enter event. If you also want to log
|
||||
whether the syscall failed or succeeded, remove the direction filter and add the evt.arg.res_or_fd output field.
|
||||
condition: >
|
||||
evt.type=bpf and evt.dir=>
|
||||
and (evt.arg.cmd=5 or evt.arg.cmd=BPF_PROG_LOAD)
|
||||
and not bpf_profiled_procs
|
||||
output: BPF Program Not Profiled | bpf_cmd=%evt.arg.cmd evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_incubating, host, container, mitre_persistence, TA0003]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2023 The Falco Authors.
|
||||
# Copyright (C) 2025 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -24,7 +25,11 @@
|
|||
|
||||
# Starting with version 8, the Falco engine supports exceptions.
|
||||
# However the Falco rules file does not use them by default.
|
||||
- required_engine_version: 26
|
||||
- required_engine_version: 0.50.0
|
||||
|
||||
- required_plugin_versions:
|
||||
- name: container
|
||||
version: 0.2.2
|
||||
|
||||
# Currently disabled as read/write are ignored syscalls. The nearly
|
||||
# similar open_write/open_read check for files being opened for
|
||||
|
@ -67,7 +72,7 @@
|
|||
# on the identity of the process performing an action such as opening
|
||||
# a file, etc., we require that the process name be known.
|
||||
- macro: proc_name_exists
|
||||
condition: (proc.name!="<NA>")
|
||||
condition: (not proc.name in ("<NA>","N/A"))
|
||||
|
||||
- macro: rename
|
||||
condition: (evt.type in (rename, renameat, renameat2))
|
||||
|
@ -268,7 +273,7 @@
|
|||
(fd.cnet in (allowed_inbound_source_networks)) or
|
||||
(fd.cip.name in (allowed_inbound_source_domains)))
|
||||
enabled: false
|
||||
output: Disallowed inbound connection source (connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Disallowed inbound connection source | connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=%fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_sandbox, host, container, network, mitre_command_and_control, TA0011]
|
||||
|
||||
|
@ -311,26 +316,18 @@
|
|||
fd.directory in (shell_config_directories))
|
||||
and not proc.name in (shell_binaries)
|
||||
enabled: false
|
||||
output: A shell configuration file was read by a non-shell program (file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: A shell configuration file was read by a non-shell program | file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority:
|
||||
WARNING
|
||||
tags: [maturity_sandbox, host, container, filesystem, mitre_discovery, T1546.004]
|
||||
|
||||
# Use this to test whether the event occurred within a container.
|
||||
# When displaying container information in the output field, use
|
||||
# %container.info, without any leading term (file=%fd.name
|
||||
# %container.info user=%user.name user_loginuid=%user.loginuid, and not file=%fd.name
|
||||
# container=%container.info user=%user.name user_loginuid=%user.loginuid). The output will change
|
||||
# based on the context and whether or not -pk/-pm/-pc was specified on
|
||||
# the command line.
|
||||
- macro: container
|
||||
condition: (container.id != host)
|
||||
|
||||
- macro: container_started
|
||||
condition: >
|
||||
((evt.type = container or
|
||||
(spawned_process and proc.vpid=1)) and
|
||||
container.image.repository != incomplete)
|
||||
(spawned_process and proc.vpid=1 and container)
|
||||
|
||||
# Possible scripts run by sshkit
|
||||
- list: sshkit_script_binaries
|
||||
|
@ -585,6 +582,11 @@
|
|||
- macro: user_known_update_package_registry
|
||||
condition: (never_true)
|
||||
|
||||
# todo!: the usage of `evt.arg*` filter check in the output should be avoided
|
||||
# when more than one event type is involved because some event will populate
|
||||
# the filtercheck and others will always return <NA>. In this specific
|
||||
# rule, 'open_write' events don't have a `%evt.arg.newpath` argument for example so
|
||||
# we will always return `<NA>`.
|
||||
- rule: Update Package Repository
|
||||
desc: >
|
||||
This rule generically detects updates to package repositories and can be seen as an auditing measure.
|
||||
|
@ -595,7 +597,7 @@
|
|||
and not package_mgmt_ancestor_procs
|
||||
and not exe_running_docker_save
|
||||
and not user_known_update_package_registry
|
||||
output: Repository files get updated (newpath=%evt.arg.newpath file=%fd.name pcmdline=%proc.pcmdline evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Repository files get updated | newpath=%evt.arg.newpath file=%fd.name pcmdline=%proc.pcmdline evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority:
|
||||
NOTICE
|
||||
tags: [maturity_sandbox, host, container, filesystem, mitre_execution, T1072]
|
||||
|
@ -620,7 +622,7 @@
|
|||
and not python_running_get_pip
|
||||
and not python_running_ms_oms
|
||||
and not user_known_write_below_binary_dir_activities
|
||||
output: File below a known binary directory opened for writing (file=%fd.name pcmdline=%proc.pcmdline gparent=%proc.aname[2] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: File below a known binary directory opened for writing | file=%fd.name pcmdline=%proc.pcmdline gparent=%proc.aname[2] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: ERROR
|
||||
tags: [maturity_sandbox, host, container, filesystem, mitre_persistence, T1543]
|
||||
|
||||
|
@ -675,12 +677,12 @@
|
|||
and not google_accounts_daemon_writing_ssh
|
||||
and not cloud_init_writing_ssh
|
||||
and not user_known_write_monitored_dir_conditions
|
||||
output: File below a monitored directory opened for writing (file=%fd.name pcmdline=%proc.pcmdline gparent=%proc.aname[2] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: File below a monitored directory opened for writing | file=%fd.name pcmdline=%proc.pcmdline gparent=%proc.aname[2] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: ERROR
|
||||
tags: [maturity_sandbox, host, container, filesystem, mitre_persistence, T1543]
|
||||
|
||||
- list: safe_etc_dirs
|
||||
items: [/etc/cassandra, /etc/ssl/certs/java, /etc/logstash, /etc/nginx/conf.d, /etc/container_environment, /etc/hrmconfig, /etc/fluent/configs.d. /etc/alertmanager]
|
||||
items: [/etc/cassandra, /etc/ssl/certs/java, /etc/logstash, /etc/nginx/conf.d, /etc/container_environment, /etc/hrmconfig, /etc/fluent/configs.d, /etc/alertmanager]
|
||||
|
||||
- macro: fluentd_writing_conf_files
|
||||
condition: (proc.name=start-fluentd and fd.name in (/etc/fluent/fluent.conf, /etc/td-agent/td-agent.conf))
|
||||
|
@ -828,6 +830,17 @@
|
|||
fd.name startswith /etc/ssh/ssh_monitor_config_ or
|
||||
fd.name startswith /etc/ssh/ssh_config_))
|
||||
|
||||
- macro: etckeeper_activities
|
||||
condition: (never_true)
|
||||
|
||||
- macro: etckeeper
|
||||
condition: >
|
||||
(proc.aname = etckeeper
|
||||
or (proc.aname in (50vcs-commit, 30store-metadata, 50uncommitted-c))
|
||||
and (fd.name startswith /etc/.git/
|
||||
or fd.name = /etc/.etckeeper)
|
||||
and etckeeper_activities)
|
||||
|
||||
- macro: multipath_writing_conf
|
||||
condition: (proc.name = multipath and fd.name startswith /etc/multipath/)
|
||||
|
||||
|
@ -955,6 +968,7 @@
|
|||
and not automount_using_mtab
|
||||
and not mcafee_writing_cma_d
|
||||
and not avinetworks_supervisor_writing_ssh
|
||||
and not etckeeper
|
||||
and not multipath_writing_conf
|
||||
and not calico_node)
|
||||
|
||||
|
@ -965,7 +979,7 @@
|
|||
profiling of your environment can transform this rule into an effective rule for detecting unusual behavior associated with system
|
||||
changes, including compliance-related cases.
|
||||
condition: write_etc_common
|
||||
output: File below /etc opened for writing (file=%fd.name pcmdline=%proc.pcmdline gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: File below /etc opened for writing | file=%fd.name pcmdline=%proc.pcmdline gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: ERROR
|
||||
tags: [maturity_sandbox, host, container, filesystem, mitre_persistence, T1098]
|
||||
|
||||
|
@ -1068,7 +1082,7 @@
|
|||
and not known_root_conditions
|
||||
and not user_known_write_root_conditions
|
||||
and not user_known_write_below_root_activities
|
||||
output: File below / or /root opened for writing (file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: File below / or /root opened for writing | file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: ERROR
|
||||
tags: [maturity_sandbox, host, container, filesystem, mitre_persistence, TA0003]
|
||||
|
||||
|
@ -1097,7 +1111,7 @@
|
|||
and not exe_running_docker_save
|
||||
and not amazon_linux_running_python_yum
|
||||
and not user_known_write_rpm_database_activities
|
||||
output: rpm database opened for writing by a non-rpm program (file=%fd.name pcmdline=%proc.pcmdline evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: rpm database opened for writing by a non-rpm program | file=%fd.name pcmdline=%proc.pcmdline evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: ERROR
|
||||
tags: [maturity_sandbox, host, container, filesystem, software_mgmt, mitre_persistence, T1072]
|
||||
|
||||
|
@ -1116,7 +1130,7 @@
|
|||
and not package_mgmt_procs
|
||||
and not exe_running_docker_save
|
||||
and not user_known_modify_bin_dir_activities
|
||||
output: File below known binary directory renamed/removed (file=%fd.name pcmdline=%proc.pcmdline evt_args=%evt.args evt_type=%evt.type evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: File below known binary directory renamed/removed | file=%fd.name pcmdline=%proc.pcmdline evt_args=%evt.args evt_type=%evt.type evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: ERROR
|
||||
tags: [maturity_sandbox, host, container, filesystem, mitre_defense_evasion, T1222.002]
|
||||
|
||||
|
@ -1135,7 +1149,7 @@
|
|||
and not package_mgmt_procs
|
||||
and not user_known_mkdir_bin_dir_activities
|
||||
and not exe_running_docker_save
|
||||
output: Directory below known binary directory created (directory=%evt.arg.path evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Directory below known binary directory created | directory=%evt.arg.path evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: ERROR
|
||||
tags: [maturity_sandbox, host, container, filesystem, mitre_persistence, T1222.002]
|
||||
|
||||
|
@ -1229,18 +1243,18 @@
|
|||
# below /etc as well, but the globbing mechanism
|
||||
# doesn't allow exclusions of a full pattern, only single characters.
|
||||
- macro: sensitive_mount
|
||||
condition: (container.mount.dest[/proc*] != "N/A" or
|
||||
container.mount.dest[/var/run/docker.sock] != "N/A" or
|
||||
container.mount.dest[/var/run/crio/crio.sock] != "N/A" or
|
||||
container.mount.dest[/run/containerd/containerd.sock] != "N/A" or
|
||||
container.mount.dest[/var/lib/kubelet] != "N/A" or
|
||||
container.mount.dest[/var/lib/kubelet/pki] != "N/A" or
|
||||
container.mount.dest[/] != "N/A" or
|
||||
container.mount.dest[/home/admin] != "N/A" or
|
||||
container.mount.dest[/etc] != "N/A" or
|
||||
container.mount.dest[/etc/kubernetes] != "N/A" or
|
||||
container.mount.dest[/etc/kubernetes/manifests] != "N/A" or
|
||||
container.mount.dest[/root*] != "N/A")
|
||||
condition: (not container.mount.dest[/proc*] in ("<NA>","N/A") or
|
||||
not container.mount.dest[/var/run/docker.sock] in ("<NA>","N/A") or
|
||||
not container.mount.dest[/var/run/crio/crio.sock] in ("<NA>","N/A") or
|
||||
not container.mount.dest[/run/containerd/containerd.sock] in ("<NA>","N/A") or
|
||||
not container.mount.dest[/var/lib/kubelet] in ("<NA>","N/A") or
|
||||
not container.mount.dest[/var/lib/kubelet/pki] in ("<NA>","N/A") or
|
||||
not container.mount.dest[/] in ("<NA>","N/A") or
|
||||
not container.mount.dest[/home/admin] in ("<NA>","N/A") or
|
||||
not container.mount.dest[/etc] in ("<NA>","N/A") or
|
||||
not container.mount.dest[/etc/kubernetes] in ("<NA>","N/A") or
|
||||
not container.mount.dest[/etc/kubernetes/manifests] in ("<NA>","N/A") or
|
||||
not container.mount.dest[/root*] in ("<NA>","N/A"))
|
||||
|
||||
- rule: Launch Sensitive Mount Container
|
||||
desc: >
|
||||
|
@ -1249,11 +1263,10 @@
|
|||
varies based on your environment.
|
||||
condition: >
|
||||
container_started
|
||||
and container
|
||||
and sensitive_mount
|
||||
and not falco_sensitive_mount_containers
|
||||
and not user_sensitive_mount_containers
|
||||
output: Container with sensitive mount started (mounts=%container.mounts evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Container with sensitive mount started | mounts=%container.mounts evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: INFO
|
||||
tags: [maturity_sandbox, container, cis, mitre_execution, T1610]
|
||||
|
||||
|
@ -1276,9 +1289,8 @@
|
|||
this can be challenging to manage.
|
||||
condition: >
|
||||
container_started
|
||||
and container
|
||||
and not allowed_containers
|
||||
output: Container started and not in allowed list (evt_type=%evt.type user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Container started and not in allowed list | evt_type=%evt.type user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: WARNING
|
||||
tags: [maturity_sandbox, container, mitre_lateral_movement, T1610]
|
||||
|
||||
|
@ -1295,7 +1307,7 @@
|
|||
inbound
|
||||
and interpreted_procs
|
||||
enabled: false
|
||||
output: Interpreted program received/listened for network traffic (connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Interpreted program received/listened for network traffic | connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=%fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_sandbox, host, container, network, mitre_exfiltration, TA0011]
|
||||
|
||||
|
@ -1308,7 +1320,7 @@
|
|||
outbound
|
||||
and interpreted_procs
|
||||
enabled: false
|
||||
output: Interpreted program performed outgoing network connection (connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Interpreted program performed outgoing network connection | connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=%fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_sandbox, host, container, network, mitre_exfiltration, TA0011]
|
||||
|
||||
|
@ -1334,7 +1346,7 @@
|
|||
and fd.sport <= 32767
|
||||
and not nodeport_containers
|
||||
enabled: false
|
||||
output: Unexpected K8s NodePort Connection (connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Unexpected K8s NodePort Connection | connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=%fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_sandbox, network, k8s, container, mitre_persistence, T1205.001, NIST_800-53_AC-6]
|
||||
|
||||
|
@ -1358,7 +1370,7 @@
|
|||
and not user_known_create_hidden_file_activities
|
||||
and not exe_running_docker_save
|
||||
enabled: false
|
||||
output: Hidden file or directory created (file=%fd.name newpath=%evt.arg.newpath evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Hidden file or directory created | file=%fd.name newpath=%evt.arg.newpath evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority:
|
||||
NOTICE
|
||||
tags: [maturity_sandbox, host, container, filesystem, mitre_defense_evasion, T1564.001]
|
||||
|
@ -1469,7 +1481,7 @@
|
|||
net_miner_pool
|
||||
and not trusted_images_query_miner_domain_dns
|
||||
enabled: false
|
||||
output: Outbound connection to IP/Port flagged by https://cryptoioc.ch (ip=%fd.rip connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Outbound connection to IP/Port flagged by https://cryptoioc.ch | ip=%fd.rip connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=%fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: CRITICAL
|
||||
tags: [maturity_sandbox, host, container, network, mitre_impact, T1496]
|
||||
|
||||
|
@ -1483,18 +1495,15 @@
|
|||
proc.cmdline contains "stratum2+tcp" or
|
||||
proc.cmdline contains "stratum+ssl" or
|
||||
proc.cmdline contains "stratum2+ssl")
|
||||
output: Possible miner running (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Possible miner running | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: CRITICAL
|
||||
tags: [maturity_sandbox, host, container, process, mitre_impact, T1496]
|
||||
|
||||
- list: k8s_client_binaries
|
||||
items: [docker, kubectl, crictl]
|
||||
|
||||
# TODO: Remove k8s.gcr.io reference after 01/Dec/2023
|
||||
- list: user_known_k8s_ns_kube_system_images
|
||||
items: [
|
||||
k8s.gcr.io/fluentd-gcp-scaler,
|
||||
k8s.gcr.io/node-problem-detector/node-problem-detector,
|
||||
registry.k8s.io/fluentd-gcp-scaler,
|
||||
registry.k8s.io/node-problem-detector/node-problem-detector
|
||||
]
|
||||
|
@ -1505,8 +1514,7 @@
|
|||
]
|
||||
|
||||
# Whitelist for known docker client binaries run inside container
|
||||
# - k8s.gcr.io/fluentd-gcp-scaler / registry.k8s.io/fluentd-gcp-scaler in GCP/GKE
|
||||
# TODO: Remove k8s.gcr.io reference after 01/Dec/2023
|
||||
# - registry.k8s.io/fluentd-gcp-scaler in GCP/GKE
|
||||
- macro: user_known_k8s_client_container
|
||||
condition: >
|
||||
(k8s.ns.name="kube-system" and container.image.repository in (user_known_k8s_ns_kube_system_images)) or container.image.repository in (user_known_k8s_images)
|
||||
|
@ -1524,7 +1532,7 @@
|
|||
and container
|
||||
and not user_known_k8s_client_container_parens
|
||||
and proc.name in (k8s_client_binaries)
|
||||
output: Kubernetes Client Tool Launched in Container (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Kubernetes Client Tool Launched in Container | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: WARNING
|
||||
tags: [maturity_sandbox, container, mitre_execution, T1610]
|
||||
|
||||
|
@ -1557,7 +1565,7 @@
|
|||
and not runc_writing_var_lib_docker
|
||||
and not user_known_container_drift_activities
|
||||
enabled: false
|
||||
output: Drift detected (chmod), new executable created in a container (filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Drift detected (chmod), new executable created in a container | filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: ERROR
|
||||
tags: [maturity_sandbox, container, process, filesystem, mitre_execution, T1059]
|
||||
|
||||
|
@ -1577,7 +1585,7 @@
|
|||
and not runc_writing_var_lib_docker
|
||||
and not user_known_container_drift_activities
|
||||
enabled: false
|
||||
output: Drift detected (open+create), new executable created in a container (filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Drift detected (open+create), new executable created in a container | filename=%evt.arg.filename name=%evt.arg.name mode=%evt.arg.mode evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: ERROR
|
||||
tags: [maturity_sandbox, container, process, filesystem, mitre_execution, T1059]
|
||||
|
||||
|
@ -1601,7 +1609,7 @@
|
|||
and user.uid=0
|
||||
and not user_known_run_as_root_container
|
||||
enabled: false
|
||||
output: Container launched with root user privilege (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Container launched with root user privilege | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: INFO
|
||||
tags: [maturity_sandbox, container, process, users, mitre_execution, T1610]
|
||||
|
||||
|
@ -1618,7 +1626,7 @@
|
|||
and (proc.name=sudoedit or proc.name = sudo)
|
||||
and (proc.args contains -s or proc.args contains -i or proc.args contains --login)
|
||||
and (proc.args contains "\ " or proc.args endswith \)
|
||||
output: Detect Sudo Privilege Escalation Exploit (CVE-2021-3156) (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Detect Sudo Privilege Escalation Exploit (CVE-2021-3156) | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: CRITICAL
|
||||
tags: [maturity_sandbox, host, container, filesystem, users, mitre_privilege_escalation, T1548.003]
|
||||
|
||||
|
@ -1634,7 +1642,7 @@
|
|||
and user.uid != 0
|
||||
and (evt.rawres >= 0 or evt.res != -1)
|
||||
and not proc.name in (user_known_userfaultfd_processes)
|
||||
output: An userfaultfd syscall was successfully executed by an unprivileged user (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: An userfaultfd syscall was successfully executed by an unprivileged user | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: CRITICAL
|
||||
tags: [maturity_sandbox, host, container, process, mitre_defense_evasion, TA0005]
|
||||
|
||||
|
@ -1650,7 +1658,7 @@
|
|||
and user.uid != 0
|
||||
and proc.name=pkexec
|
||||
and proc.args = ''
|
||||
output: Detect Polkit pkexec Local Privilege Escalation Exploit (CVE-2021-4034) (args=%proc.args evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Detect Polkit pkexec Local Privilege Escalation Exploit (CVE-2021-4034) | args=%proc.args evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: CRITICAL
|
||||
tags: [maturity_sandbox, host, container, process, users, mitre_privilege_escalation, TA0004]
|
||||
|
||||
|
@ -1666,7 +1674,7 @@
|
|||
condition: >
|
||||
java_network_read
|
||||
and evt.buffer bcontains cafebabe
|
||||
output: Java process class file download (server_ip=%fd.sip server_port=%fd.sport connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Java process class file download | server_ip=%fd.sip server_port=%fd.sport connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=%fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: CRITICAL
|
||||
enabled: false
|
||||
tags: [maturity_sandbox, host, container, process, mitre_initial_access, T1190]
|
||||
|
@ -1688,31 +1696,10 @@
|
|||
and not docker_procs
|
||||
and not proc.cmdline = "runc:[1:CHILD] init"
|
||||
enabled: false
|
||||
output: Detect Potential Container Breakout Exploit (CVE-2019-5736) (file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Detect Potential Container Breakout Exploit (CVE-2019-5736) | file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: WARNING
|
||||
tags: [maturity_sandbox, container, filesystem, mitre_initial_access, T1611]
|
||||
|
||||
- list: bpf_profiled_binaries
|
||||
items: [falco, bpftool]
|
||||
|
||||
- macro: bpf_profiled_procs
|
||||
condition: (proc.name in (bpf_profiled_binaries))
|
||||
|
||||
- rule: BPF Program Not Profiled
|
||||
desc: >
|
||||
BPF is a kernel technology that can be misused for malicious purposes, like "Linux Kernel Module Injection". This
|
||||
rule should be considered an auditing rule to notify you of any unprofiled BPF tools running in your environment.
|
||||
However, it requires customization after profiling your environment. BPF-powered agents make bpf syscalls all the
|
||||
time, so this rule only sends logs for BPF_PROG_LOAD calls (bpf cmd=5) in the enter event. If you also want to log
|
||||
whether the syscall failed or succeeded, remove the direction filter and add the evt.arg.res_or_fd output field.
|
||||
condition: >
|
||||
evt.type=bpf and evt.dir=>
|
||||
and evt.arg.cmd=5
|
||||
and not bpf_profiled_procs
|
||||
output: BPF Program Not Profiled (bpf_cmd=%evt.arg.cmd evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
priority: NOTICE
|
||||
tags: [maturity_sandbox, host, container, mitre_persistence, TA0003]
|
||||
|
||||
- list: known_decode_payload_containers
|
||||
items: []
|
||||
|
||||
|
@ -1732,7 +1719,7 @@
|
|||
and container
|
||||
and base64_decoding
|
||||
and not container.image.repository in (known_decode_payload_containers)
|
||||
output: Decoding Payload in Container (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Decoding Payload in Container | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: INFO
|
||||
tags: [maturity_sandbox, container, process, mitre_command_and_control, T1132]
|
||||
- list: recon_binaries
|
||||
|
@ -1755,6 +1742,25 @@
|
|||
and recon_binaries_procs
|
||||
and proc.tty != 0
|
||||
and proc.is_vpgid_leader=true
|
||||
output: Basic Interactive Reconnaissance (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Basic Interactive Reconnaissance | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: NOTICE
|
||||
tags: [maturity_sandbox, host, container, process, mitre_reconnaissance, TA0043]
|
||||
|
||||
- rule: Netcat/Socat Remote Code Execution on Host
|
||||
desc: >
|
||||
Netcat/Socat Program runs on host that allows remote code execution and may be utilized
|
||||
as a part of a variety of reverse shell payload https://github.com/swisskyrepo/PayloadsAllTheThings/.
|
||||
These programs are of higher relevance as they are commonly installed on UNIX-like operating systems.
|
||||
condition: >
|
||||
spawned_process
|
||||
and not container
|
||||
and ((proc.name = "nc" and (proc.cmdline contains "-e" or
|
||||
proc.cmdline contains "-c")) or
|
||||
(proc.name = "ncat" and (proc.args contains "--sh-exec" or
|
||||
proc.args contains "--exec" or proc.args contains "-e " or
|
||||
proc.args contains "-c " or proc.args contains "--lua-exec")) or
|
||||
(proc.name = 'socat' and (proc.args contains "EXEC" or
|
||||
proc.args contains "SYSTEM")))
|
||||
output: Netcat/Socat runs on host that allows remote code execution | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: WARNING
|
||||
tags: [maturity_sandbox, host, network, process, mitre_execution, T1059]
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Copyright (C) 2023 The Falco Authors.
|
||||
# Copyright (C) 2025 The Falco Authors.
|
||||
#
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
|
@ -24,7 +25,11 @@
|
|||
|
||||
# Starting with version 8, the Falco engine supports exceptions.
|
||||
# However the Falco rules file does not use them by default.
|
||||
- required_engine_version: 26
|
||||
- required_engine_version: 0.50.0
|
||||
|
||||
- required_plugin_versions:
|
||||
- name: container
|
||||
version: 0.2.2
|
||||
|
||||
# Currently disabled as read/write are ignored syscalls. The nearly
|
||||
# similar open_write/open_read check for files being opened for
|
||||
|
@ -73,8 +78,9 @@
|
|||
# the process name may be missing. For some rules that really depend
|
||||
# on the identity of the process performing an action such as opening
|
||||
# a file, etc., we require that the process name be known.
|
||||
# TODO: At the moment we keep the `N/A` variant for compatibility with old scap-files
|
||||
- macro: proc_name_exists
|
||||
condition: (proc.name!="<NA>")
|
||||
condition: (not proc.name in ("<NA>","N/A"))
|
||||
|
||||
- macro: spawned_process
|
||||
condition: (evt.type in (execve, execveat) and evt.dir=<)
|
||||
|
@ -89,7 +95,7 @@
|
|||
condition: (evt.type in (init_module, finit_module) and evt.dir=<)
|
||||
|
||||
- macro: dup
|
||||
condition: (evt.type in (dup, dup2, dup3))
|
||||
condition: (evt.type in (dup, dup2, dup3) and evt.dir=<)
|
||||
|
||||
# File categories
|
||||
- macro: etc_dir
|
||||
|
@ -157,7 +163,7 @@
|
|||
apt-listchanges, unattended-upgr, apt-add-reposit, apt-cache, apt.systemd.dai
|
||||
]
|
||||
- list: python_package_managers
|
||||
items: [pip, pip3, conda]
|
||||
items: [pip, pip3, conda, uv]
|
||||
|
||||
# The truncated dpkg-preconfigu is intentional, process names are
|
||||
# truncated at the falcosecurity-libs level.
|
||||
|
@ -206,7 +212,7 @@
|
|||
|
||||
- macro: sensitive_files
|
||||
condition: >
|
||||
((fd.name startswith /etc and fd.name in (sensitive_file_names)) or
|
||||
(fd.name in (sensitive_file_names) or
|
||||
fd.directory in (/etc/sudoers.d, /etc/pam.d))
|
||||
|
||||
# Indicates that the process is new. Currently detected using time
|
||||
|
@ -215,12 +221,6 @@
|
|||
condition: (proc.duration <= 5000000000)
|
||||
|
||||
# Use this to test whether the event occurred within a container.
|
||||
# When displaying container information in the output field, use
|
||||
# %container.info, without any leading term (file=%fd.name
|
||||
# %container.info user=%user.name user_loginuid=%user.loginuid, and not file=%fd.name
|
||||
# container=%container.info user=%user.name user_loginuid=%user.loginuid). The output will change
|
||||
# based on the context and whether or not -pk/-pm/-pc was specified on
|
||||
# the command line.
|
||||
- macro: container
|
||||
condition: (container.id != host)
|
||||
|
||||
|
@ -328,7 +328,7 @@
|
|||
and directory_traversal
|
||||
and not proc.pname in (shell_binaries)
|
||||
enabled: true
|
||||
output: Read monitored file via directory traversal (file=%fd.name fileraw=%fd.nameraw gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Read monitored file via directory traversal | file=%fd.name fileraw=%fd.nameraw gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: WARNING
|
||||
tags: [maturity_stable, host, container, filesystem, mitre_credential_access, T1555]
|
||||
|
||||
|
@ -354,7 +354,7 @@
|
|||
and not proc_is_new
|
||||
and proc.name!="sshd"
|
||||
and not user_known_read_sensitive_files_activities
|
||||
output: Sensitive file opened for reading by trusted program after startup (file=%fd.name pcmdline=%proc.pcmdline gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Sensitive file opened for reading by trusted program after startup | file=%fd.name pcmdline=%proc.pcmdline gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: WARNING
|
||||
tags: [maturity_stable, host, container, filesystem, mitre_credential_access, T1555]
|
||||
|
||||
|
@ -363,7 +363,8 @@
|
|||
iptables, ps, lsb_release, check-new-relea, dumpe2fs, accounts-daemon, sshd,
|
||||
vsftpd, systemd, mysql_install_d, psql, screen, debconf-show, sa-update,
|
||||
pam-auth-update, pam-config, /usr/sbin/spamd, polkit-agent-he, lsattr, file, sosreport,
|
||||
scxcimservera, adclient, rtvscand, cockpit-session, userhelper, ossec-syscheckd
|
||||
scxcimservera, adclient, rtvscand, cockpit-session, userhelper, ossec-syscheckd,
|
||||
sshd-session
|
||||
]
|
||||
|
||||
# Add conditions to this macro (probably in a separate file,
|
||||
|
@ -426,7 +427,7 @@
|
|||
and not linux_bench_reading_etc_shadow
|
||||
and not user_known_read_sensitive_files_activities
|
||||
and not user_read_sensitive_file_containers
|
||||
output: Sensitive file opened for reading by non-trusted program (file=%fd.name gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Sensitive file opened for reading by non-trusted program | file=%fd.name gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: WARNING
|
||||
tags: [maturity_stable, host, container, filesystem, mitre_credential_access, T1555]
|
||||
|
||||
|
@ -598,7 +599,7 @@
|
|||
and not rabbitmqctl_running_scripts
|
||||
and not run_by_appdynamics
|
||||
and not user_shell_container_exclusions
|
||||
output: Shell spawned by untrusted binary (parent_exe=%proc.pexe parent_exepath=%proc.pexepath pcmdline=%proc.pcmdline gparent=%proc.aname[2] ggparent=%proc.aname[3] aname[4]=%proc.aname[4] aname[5]=%proc.aname[5] aname[6]=%proc.aname[6] aname[7]=%proc.aname[7] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Shell spawned by untrusted binary | parent_exe=%proc.pexe parent_exepath=%proc.pexepath pcmdline=%proc.pcmdline gparent=%proc.aname[2] ggparent=%proc.aname[3] aname[4]=%proc.aname[4] aname[5]=%proc.aname[5] aname[6]=%proc.aname[6] aname[7]=%proc.aname[7] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: NOTICE
|
||||
tags: [maturity_stable, host, container, process, shell, mitre_execution, T1059.004]
|
||||
|
||||
|
@ -633,7 +634,6 @@
|
|||
- public.ecr.aws/falcosecurity/falco-no-driver
|
||||
|
||||
# These container images are allowed to run with --privileged and full set of capabilities
|
||||
# TODO: Remove k8s.gcr.io reference after 01/Dec/2023
|
||||
- list: falco_privileged_images
|
||||
items: [
|
||||
falco_containers,
|
||||
|
@ -652,16 +652,12 @@
|
|||
gke.gcr.io/netd-amd64,
|
||||
gke.gcr.io/watcher-daemonset,
|
||||
gcr.io/google-containers/prometheus-to-sd,
|
||||
k8s.gcr.io/ip-masq-agent-amd64,
|
||||
k8s.gcr.io/kube-proxy,
|
||||
k8s.gcr.io/prometheus-to-sd,
|
||||
registry.k8s.io/ip-masq-agent-amd64,
|
||||
registry.k8s.io/kube-proxy,
|
||||
registry.k8s.io/prometheus-to-sd,
|
||||
quay.io/calico/node,
|
||||
sysdig/sysdig,
|
||||
sematext_images,
|
||||
k8s.gcr.io/dns/k8s-dns-node-cache,
|
||||
registry.k8s.io/dns/k8s-dns-node-cache,
|
||||
mcr.microsoft.com/oss/kubernetes/kube-proxy
|
||||
]
|
||||
|
@ -677,14 +673,14 @@
|
|||
# We also let runc:[1:CHILD] count as the parent process, which can occur
|
||||
# when we lose events and lose track of state.
|
||||
- macro: container_entrypoint
|
||||
condition: (not proc.pname exists or proc.pname in (runc:[0:PARENT], runc:[1:CHILD], runc, docker-runc, exe, docker-runc-cur, containerd-shim, systemd, crio))
|
||||
condition: (not proc.pname exists or proc.pname in (runc:[0:PARENT], runc:[1:CHILD], runc, docker-runc, exe, docker-runc-cur, containerd-shim, systemd, crio, conmon))
|
||||
|
||||
- macro: user_known_system_user_login
|
||||
condition: (never_true)
|
||||
|
||||
# Anything run interactively by root
|
||||
# - condition: evt.type != switch and user.name = root and proc.name != sshd and interactive
|
||||
# output: "Interactive root (%user.name %proc.name %evt.dir %evt.type %evt.args %fd.name)"
|
||||
# output: "Interactive root | %user.name %proc.name %evt.dir %evt.type %evt.args %fd.name"
|
||||
# priority: WARNING
|
||||
- rule: System user interactive
|
||||
desc: >
|
||||
|
@ -701,7 +697,7 @@
|
|||
and system_users
|
||||
and interactive
|
||||
and not user_known_system_user_login
|
||||
output: System user ran an interactive command (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: System user ran an interactive command | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: INFO
|
||||
tags: [maturity_stable, host, container, users, mitre_execution, T1059, NIST_800-53_AC-2]
|
||||
|
||||
|
@ -724,7 +720,7 @@
|
|||
and proc.tty != 0
|
||||
and container_entrypoint
|
||||
and not user_expected_terminal_shell_in_container_conditions
|
||||
output: A shell was spawned in a container with an attached terminal (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: A shell was spawned in a container with an attached terminal | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: NOTICE
|
||||
tags: [maturity_stable, container, shell, mitre_execution, T1059]
|
||||
|
||||
|
@ -795,7 +791,6 @@
|
|||
# allowed to contact the K8s API Server from within a container. This
|
||||
# might cover cases where the K8s infrastructure itself is running
|
||||
# within a container.
|
||||
# TODO: Remove k8s.gcr.io reference after 01/Dec/2023
|
||||
- macro: k8s_containers
|
||||
condition: >
|
||||
(container.image.repository in (gcr.io/google_containers/hyperkube-amd64,
|
||||
|
@ -807,7 +802,7 @@
|
|||
ibm_cloud_containers,
|
||||
velero/velero,
|
||||
quay.io/jetstack/cert-manager-cainjector, weaveworks/kured,
|
||||
quay.io/prometheus-operator/prometheus-operator, k8s.gcr.io/ingress-nginx/kube-webhook-certgen,
|
||||
quay.io/prometheus-operator/prometheus-operator,
|
||||
registry.k8s.io/ingress-nginx/kube-webhook-certgen, quay.io/spotahome/redis-operator,
|
||||
registry.opensource.zalan.do/acid/postgres-operator, registry.opensource.zalan.do/acid/postgres-operator-ui,
|
||||
rabbitmqoperator/cluster-operator, quay.io/kubecost1/kubecost-cost-model,
|
||||
|
@ -835,7 +830,7 @@
|
|||
and k8s_api_server
|
||||
and not k8s_containers
|
||||
and not user_known_contact_k8s_api_server_activities
|
||||
output: Unexpected connection to K8s API Server from container (connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Unexpected connection to K8s API Server from container | connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=%fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_stable, container, network, k8s, mitre_discovery, T1565]
|
||||
|
||||
|
@ -855,7 +850,7 @@
|
|||
proc.args contains "--exec" or proc.args contains "-e " or
|
||||
proc.args contains "-c " or proc.args contains "--lua-exec"))
|
||||
)
|
||||
output: Netcat runs inside container that allows remote code execution (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Netcat runs inside container that allows remote code execution | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: WARNING
|
||||
tags: [maturity_stable, container, network, process, mitre_execution, T1059]
|
||||
|
||||
|
@ -897,7 +892,7 @@
|
|||
proc.args contains "id_ecdsa"
|
||||
)
|
||||
))
|
||||
output: Grep private keys or passwords activities found (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Grep private keys or passwords activities found | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority:
|
||||
WARNING
|
||||
tags: [maturity_stable, host, container, process, filesystem, mitre_credential_access, T1552.001]
|
||||
|
@ -921,6 +916,12 @@
|
|||
container.image.repository endswith "openshift3/ose-logging-fluentd" or
|
||||
container.image.repository endswith "containernetworking/azure-npm")
|
||||
|
||||
- macro: containerd_activities
|
||||
condition: (proc.name=containerd and (fd.name startswith "/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/" or
|
||||
fd.name startswith "/var/lib/rancher/k3s/agent/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots" or
|
||||
fd.name startswith "/var/lib/containerd/tmpmounts/" or
|
||||
fd.name startswith "/var/lib/rancher/k3s/agent/containerd/tmpmounts/"))
|
||||
|
||||
- rule: Clear Log Activities
|
||||
desc: >
|
||||
Detect clearing of critical access log files, typically done to erase evidence that could be attributed to an adversary's
|
||||
|
@ -930,9 +931,10 @@
|
|||
open_write
|
||||
and access_log_files
|
||||
and evt.arg.flags contains "O_TRUNC"
|
||||
and not containerd_activities
|
||||
and not trusted_logging_images
|
||||
and not allowed_clear_log_files
|
||||
output: Log files were tampered (file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Log files were tampered | file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority:
|
||||
WARNING
|
||||
tags: [maturity_stable, host, container, filesystem, mitre_defense_evasion, T1070, NIST_800-53_AU-10]
|
||||
|
@ -954,7 +956,7 @@
|
|||
spawned_process
|
||||
and clear_data_procs
|
||||
and not user_known_remove_data_activities
|
||||
output: Bulk data has been removed from disk (file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Bulk data has been removed from disk | file=%fd.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority:
|
||||
WARNING
|
||||
tags: [maturity_stable, host, container, process, filesystem, mitre_impact, T1485]
|
||||
|
@ -967,7 +969,7 @@
|
|||
condition: >
|
||||
create_symlink
|
||||
and (evt.arg.target in (sensitive_file_names) or evt.arg.target in (sensitive_directory_names))
|
||||
output: Symlinks created over sensitive files (target=%evt.arg.target linkpath=%evt.arg.linkpath evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Symlinks created over sensitive files | target=%evt.arg.target linkpath=%evt.arg.linkpath evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: WARNING
|
||||
tags: [maturity_stable, host, container, filesystem, mitre_credential_access, T1555]
|
||||
|
||||
|
@ -979,7 +981,7 @@
|
|||
condition: >
|
||||
create_hardlink
|
||||
and (evt.arg.oldpath in (sensitive_file_names))
|
||||
output: Hardlinks created over sensitive files (target=%evt.arg.target linkpath=%evt.arg.linkpath evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Hardlinks created over sensitive files | target=%evt.arg.oldpath linkpath=%evt.arg.newpath evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: WARNING
|
||||
tags: [maturity_stable, host, container, filesystem, mitre_credential_access, T1555]
|
||||
|
||||
|
@ -992,11 +994,11 @@
|
|||
and privilege escalation (CVE-2020-14386) by an attacker. Noise can be reduced by using the user_known_packet_socket_binaries
|
||||
template list.
|
||||
condition: >
|
||||
evt.type=socket
|
||||
evt.type=socket and evt.dir=>
|
||||
and container
|
||||
and evt.arg[0] contains AF_PACKET
|
||||
and evt.arg.domain contains AF_PACKET
|
||||
and not proc.name in (user_known_packet_socket_binaries)
|
||||
output: Packet socket was created in a container (socket_info=%evt.args connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Packet socket was created in a container | socket_info=%evt.args connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=%fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_stable, container, network, mitre_credential_access, T1557.002]
|
||||
|
||||
|
@ -1029,7 +1031,7 @@
|
|||
and evt.rawres in (0, 1, 2)
|
||||
and fd.type in ("ipv4", "ipv6")
|
||||
and not user_known_stand_streams_redirect_activities
|
||||
output: Redirect stdout/stdin to network connection (gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] fd.sip=%fd.sip connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Redirect stdout/stdin to network connection | gparent=%proc.aname[2] ggparent=%proc.aname[3] gggparent=%proc.aname[4] fd.sip=%fd.sip connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=%fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_stable, container, network, process, mitre_execution, T1059]
|
||||
|
||||
|
@ -1046,7 +1048,7 @@
|
|||
and container
|
||||
and thread.cap_effective icontains sys_module
|
||||
and not container.image.repository in (allowed_container_images_loading_kernel_module)
|
||||
output: Linux Kernel Module injection from container (parent_exepath=%proc.pexepath gparent=%proc.aname[2] gexepath=%proc.aexepath[2] module=%proc.args res=%evt.res evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Linux Kernel Module injection from container | parent_exepath=%proc.pexepath gparent=%proc.aname[2] gexepath=%proc.aexepath[2] module=%proc.args res=%evt.res evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: WARNING
|
||||
tags: [maturity_stable, host, container, process, mitre_persistence, TA0003]
|
||||
|
||||
|
@ -1059,7 +1061,7 @@
|
|||
and container
|
||||
and container.privileged=true
|
||||
and proc.name=debugfs
|
||||
output: Debugfs launched started in a privileged container (evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Debugfs launched started in a privileged container | evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: WARNING
|
||||
tags: [maturity_stable, container, cis, process, mitre_privilege_escalation, T1611]
|
||||
|
||||
|
@ -1074,7 +1076,7 @@
|
|||
and fd.name endswith release_agent
|
||||
and (user.uid=0 or thread.cap_effective contains CAP_DAC_OVERRIDE)
|
||||
and thread.cap_effective contains CAP_SYS_ADMIN
|
||||
output: Detect an attempt to exploit a container escape using release_agent file (file=%fd.name cap_effective=%thread.cap_effective evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Detect an attempt to exploit a container escape using release_agent file | file=%fd.name cap_effective=%thread.cap_effective evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: CRITICAL
|
||||
tags: [maturity_stable, container, process, mitre_privilege_escalation, T1611]
|
||||
|
||||
|
@ -1106,7 +1108,7 @@
|
|||
ptrace_attach_or_injection
|
||||
and proc_name_exists
|
||||
and not known_ptrace_procs
|
||||
output: Detected ptrace PTRACE_ATTACH attempt (proc_pcmdline=%proc.pcmdline evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Detected ptrace PTRACE_ATTACH attempt | proc_pcmdline=%proc.pcmdline evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: WARNING
|
||||
tags: [maturity_stable, host, container, process, mitre_privilege_escalation, T1055.008]
|
||||
|
||||
|
@ -1119,7 +1121,7 @@
|
|||
evt.type=ptrace and evt.dir=>
|
||||
and evt.arg.request contains PTRACE_TRACEME
|
||||
and proc_name_exists
|
||||
output: Detected potential PTRACE_TRACEME anti-debug attempt (proc_pcmdline=%proc.pcmdline evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Detected potential PTRACE_TRACEME anti-debug attempt | proc_pcmdline=%proc.pcmdline evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_stable, host, container, process, mitre_defense_evasion, T1622]
|
||||
|
||||
|
@ -1141,7 +1143,7 @@
|
|||
spawned_process
|
||||
and ((grep_commands and private_aws_credentials) or
|
||||
(proc.name = "find" and proc.args endswith ".aws/credentials"))
|
||||
output: Detected AWS credentials search activity (proc_pcmdline=%proc.pcmdline proc_cwd=%proc.cwd group_gid=%group.gid group_name=%group.name user_loginname=%user.loginname evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Detected AWS credentials search activity | proc_pcmdline=%proc.pcmdline proc_cwd=%proc.cwd group_gid=%group.gid group_name=%group.name user_loginname=%user.loginname evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: WARNING
|
||||
tags: [maturity_stable, host, container, process, aws, mitre_credential_access, T1552]
|
||||
|
||||
|
@ -1160,7 +1162,7 @@
|
|||
(shell_procs and proc.args startswith "/dev/shm") or
|
||||
(proc.cwd startswith "/dev/shm/" and proc.args startswith "./" ))
|
||||
and not container.image.repository in (falco_privileged_images, trusted_images)
|
||||
output: File execution detected from /dev/shm (evt_res=%evt.res file=%fd.name proc_cwd=%proc.cwd proc_pcmdline=%proc.pcmdline user_loginname=%user.loginname group_gid=%group.gid group_name=%group.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: File execution detected from /dev/shm | evt_res=%evt.res file=%fd.name proc_cwd=%proc.cwd proc_pcmdline=%proc.pcmdline user_loginname=%user.loginname group_gid=%group.gid group_name=%group.name evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: WARNING
|
||||
tags: [maturity_stable, host, container, mitre_execution, T1059.004]
|
||||
|
||||
|
@ -1168,6 +1170,9 @@
|
|||
- list: known_drop_and_execute_containers
|
||||
items: []
|
||||
|
||||
- macro: known_drop_and_execute_activities
|
||||
condition: (never_true)
|
||||
|
||||
- rule: Drop and execute new binary in container
|
||||
desc: >
|
||||
Detect if an executable not belonging to the base image of a container is being executed.
|
||||
|
@ -1183,7 +1188,8 @@
|
|||
and container
|
||||
and proc.is_exe_upper_layer=true
|
||||
and not container.image.repository in (known_drop_and_execute_containers)
|
||||
output: Executing binary not part of base image (proc_exe=%proc.exe proc_sname=%proc.sname gparent=%proc.aname[2] proc_exe_ino_ctime=%proc.exe_ino.ctime proc_exe_ino_mtime=%proc.exe_ino.mtime proc_exe_ino_ctime_duration_proc_start=%proc.exe_ino.ctime_duration_proc_start proc_cwd=%proc.cwd container_start_ts=%container.start_ts evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
and not known_drop_and_execute_activities
|
||||
output: Executing binary not part of base image | proc_exe=%proc.exe proc_sname=%proc.sname gparent=%proc.aname[2] proc_exe_ino_ctime=%proc.exe_ino.ctime proc_exe_ino_mtime=%proc.exe_ino.mtime proc_exe_ino_ctime_duration_proc_start=%proc.exe_ino.ctime_duration_proc_start proc_cwd=%proc.cwd container_start_ts=%container.start_ts evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: CRITICAL
|
||||
tags: [maturity_stable, container, process, mitre_persistence, TA0003, PCI_DSS_11.5.1]
|
||||
|
||||
|
@ -1220,15 +1226,20 @@
|
|||
and proc.exe endswith ssh
|
||||
and fd.l4proto=tcp
|
||||
and ssh_non_standard_ports_network
|
||||
output: Disallowed SSH Connection (connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Disallowed SSH Connection | connection=%fd.name lport=%fd.lport rport=%fd.rport fd_type=%fd.type fd_proto=%fd.l4proto evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty
|
||||
priority: NOTICE
|
||||
tags: [maturity_stable, host, container, network, process, mitre_execution, T1059]
|
||||
|
||||
- list: known_memfd_execution_binaries
|
||||
items: []
|
||||
items: [runc]
|
||||
|
||||
- macro: known_memfd_execution_processes
|
||||
condition: (proc.name in (known_memfd_execution_binaries))
|
||||
condition: >
|
||||
(proc.name in (known_memfd_execution_binaries))
|
||||
or (proc.pname in (known_memfd_execution_binaries))
|
||||
or (proc.exepath = "memfd:runc_cloned:/proc/self/exe")
|
||||
or (proc.exe = "memfd:runc_cloned:/proc/self/exe")
|
||||
|
||||
|
||||
- rule: Fileless execution via memfd_create
|
||||
desc: >
|
||||
|
@ -1240,6 +1251,6 @@
|
|||
spawned_process
|
||||
and proc.is_exe_from_memfd=true
|
||||
and not known_memfd_execution_processes
|
||||
output: Fileless execution via memfd_create (container_start_ts=%container.start_ts proc_cwd=%proc.cwd evt_res=%evt.res proc_sname=%proc.sname gparent=%proc.aname[2] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags %container.info)
|
||||
output: Fileless execution via memfd_create | container_start_ts=%container.start_ts proc_cwd=%proc.cwd evt_res=%evt.res proc_sname=%proc.sname gparent=%proc.aname[2] evt_type=%evt.type user=%user.name user_uid=%user.uid user_loginuid=%user.loginuid process=%proc.name proc_exepath=%proc.exepath parent=%proc.pname command=%proc.cmdline terminal=%proc.tty exe_flags=%evt.arg.flags
|
||||
priority: CRITICAL
|
||||
tags: [maturity_stable, host, container, process, mitre_defense_evasion, T1620]
|
||||
|
|
Loading…
Reference in New Issue