Compare commits

..

313 Commits

Author SHA1 Message Date
Leonardo Di Giovanna be3800132f docs(OWNERS): add `ekoops` as approver
Signed-off-by: Leonardo Di Giovanna <41296180+ekoops@users.noreply.github.com>
2025-07-23 11:14:33 +02:00
dependabot[bot] 120881647a build(deps): Bump sigstore/cosign-installer in the actions group
Bumps the actions group with 1 update: [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer).


Updates `sigstore/cosign-installer` from 3.8.2 to 3.9.0
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](https://github.com/sigstore/cosign-installer/compare/v3.8.2...v3.9.0)

---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  dependency-version: 3.9.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-06-18 15:33:04 +02:00
Leonardo Di Giovanna d0be92e53e ci: add additional Falco releases to be tested
Signed-off-by: Leonardo Di Giovanna <leonardodigiovanna1@gmail.com>
2025-06-17 14:37:45 +02:00
Federico Di Pierro 488e6f8f0c fix(rules): fixed `container_started` macro adapting to new container plugin.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2025-06-17 12:44:44 +02:00
Melissa Kilby 4d51b1813f doc(OWNERS): move incertum (Melissa Kilby) to emeritus_approvers
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2025-06-09 11:51:54 +02:00
dependabot[bot] b4437c492f build(deps): Bump astral-sh/setup-uv from 5.4.1 to 6.1.0
Bumps [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) from 5.4.1 to 6.1.0.
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](0c5e2b8115...f0ec1fc3b3)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-version: 6.1.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-23 19:33:48 +02:00
Dirk Marwinski cb17833316 Allow new sshd-session binary to read sensitive files
Signed-off-by: Dirk Marwinski <dirk.marwinski@sap.com>
2025-05-22 10:29:39 +02:00
dependabot[bot] 4ccf111c36 build(deps): Bump sigstore/cosign-installer
Bumps the actions group with 1 update in the / directory: [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer).


Updates `sigstore/cosign-installer` from 3.8.1 to 3.8.2
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](https://github.com/sigstore/cosign-installer/compare/v3.8.1...v3.8.2)

---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  dependency-version: 3.8.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-05-14 11:06:34 +02:00
Federico Di Pierro ae6ed41a7a cleanup(rules): drop parentheses around args in rule outputs.
Use a pipe instead to divide args from rule title.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2025-05-13 14:54:29 +02:00
Federico Di Pierro 277b28eb98 update(ci): only keep master as FALCO_VERSION.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2025-05-13 14:36:29 +02:00
Federico Di Pierro 4f6510b909 chore(rules): require latest 0.2.2 container plugin version.
Also, require Falco 0.41.0 rule engine version (0.50.0).
Finally, bumped copyright year.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2025-05-13 14:36:29 +02:00
Federico Di Pierro 6f8c46deb5 cleanup(rules): drop `%container.info` from default ruleset too.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2025-05-13 14:36:29 +02:00
Federico Di Pierro f8fb73a3eb update(rules): require container plugin.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2025-05-13 14:36:29 +02:00
Federico Di Pierro 3e74a466ae fix(rules): add `conmon` to `container_entrypoint` macro.
This fixes detection of "Terminal shell in container" for podman running with crun.

Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2025-05-12 14:32:22 +02:00
Mykhailo 15bb0fea8c rules: add uv to python_package_managers list
This commit updates the Falco rules by adding uv to the python_package_managers list. The uv package manager, a tool for managing Python packages, was previously not accounted for in our detection rules. By adding uv to the list, we enable Falco to accurately identify processes spawned by this package manager.

Signed-off-by: Mykhailo <61192136+shellsession@users.noreply.github.com>
2025-05-08 17:29:57 +02:00
dependabot[bot] 75a39c1dee build(deps): Bump astral-sh/setup-uv in the actions group
Bumps the actions group with 1 update: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv).


Updates `astral-sh/setup-uv` from 5.4.0 to 5.4.1
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](22695119d7...0c5e2b8115)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-15 10:27:39 +02:00
dependabot[bot] ce46d23f61 build(deps): Bump astral-sh/setup-uv in the actions group
Bumps the actions group with 1 update: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv).


Updates `astral-sh/setup-uv` from 5.3.1 to 5.4.0
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](f94ec6bedd...22695119d7)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-04-02 11:01:15 +02:00
dependabot[bot] 371e43167e build(deps): Bump astral-sh/setup-uv in the actions group
Bumps the actions group with 1 update: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv).


Updates `astral-sh/setup-uv` from 5.3.0 to 5.3.1
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](1edb52594c...f94ec6bedd)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-03-11 11:32:35 +01:00
Kyle Fazzari 8e4ed0c27d rules: add support for k3s to containerd_activities macro
K3s is a stripped down version of Kubernetes that bundles dependencies
within it, including containerd. It puts containerd files (sockets,
tmpmounts, snapshotter overlayfs, etc.) in namespaced, non-standard
locations in an attempt to not interfere with a system-wide containerd
installation. As a result, the "Clear Log Activities" rule triggers
warnings for the bundled containerd. Fix that by including K3s'
non-standard paths in the containerd_activities macro.

Signed-off-by: Kyle Fazzari <kyrofa@ubuntu.com>
2025-03-02 09:27:47 +01:00
dependabot[bot] 1d2c6b1f0b build(deps): Bump the actions group across 1 directory with 2 updates
Bumps the actions group with 2 updates in the / directory: [astral-sh/setup-uv](https://github.com/astral-sh/setup-uv) and [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer).


Updates `astral-sh/setup-uv` from 5.2.2 to 5.3.0
- [Release notes](https://github.com/astral-sh/setup-uv/releases)
- [Commits](4db96194c3...1edb52594c)

Updates `sigstore/cosign-installer` from 3.8.0 to 3.8.1
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](https://github.com/sigstore/cosign-installer/compare/v3.8.0...v3.8.1)

---
updated-dependencies:
- dependency-name: astral-sh/setup-uv
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-24 18:09:17 +01:00
Luca Guerra 47843ac872 fix(ci): update python deps used in github pages
Signed-off-by: Luca Guerra <luca@guerra.sh>
2025-02-19 15:48:44 +01:00
Luca Guerra 740f8783e0 fix(ci): use falcosecurity/falco instead of falcosecurity/falco-no-driver
Signed-off-by: Luca Guerra <luca@guerra.sh>
2025-02-19 12:40:43 +01:00
Yutong Sun 4633f290ad rules: add runc to known_memfd_execution_binaries
Signed-off-by: Yutong Sun <yutongsu@amazon.com>
2025-02-17 16:02:34 +01:00
dependabot[bot] d8415c1bc1 build(deps): Bump sigstore/cosign-installer in the actions group
Bumps the actions group with 1 update: [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer).


Updates `sigstore/cosign-installer` from 3.7.0 to 3.8.0
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](https://github.com/sigstore/cosign-installer/compare/v3.7.0...v3.8.0)

---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-02-05 17:51:23 +01:00
Federico Di Pierro 8eef0097ca chore(ci): added Falco 0.40.0 (plus 0.39.1 and 0.39.2 that were missing) to FALCO_VERSIONS.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2025-01-29 11:09:38 +01:00
jordyb6 abf6637e0a Update(sandbox): Add Netcat/Socat Remote Code Execution on Host rule
Signed-off-by: jordyb6 <129943902+jordyb6@users.noreply.github.com>
2025-01-15 11:10:49 +01:00
Trần Đức Phú 283a62f464 fix: fix typo safe_etc_dirs
Signed-off-by: Trần Đức Phú <30786617+Phu96@users.noreply.github.com>
2024-10-23 08:44:07 +02:00
dependabot[bot] 407e99721f build(deps): Bump sigstore/cosign-installer in the actions group
Bumps the actions group with 1 update: [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer).


Updates `sigstore/cosign-installer` from 3.6.0 to 3.7.0
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](https://github.com/sigstore/cosign-installer/compare/v3.6.0...v3.7.0)

---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-10-08 17:27:09 +02:00
Aldo Lacuku e38fb3f6a7 update(ci): add 0.39.0 as supported version
Signed-off-by: Aldo Lacuku <aldo@lacuku.eu>
2024-10-02 15:44:41 +02:00
Melissa Kilby b6ad373719 chore: upgrade py deps for rules_overview_generator
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-08-20 18:20:45 +02:00
Luca Guerra bd6d337f0e update(ci): add 0.38.1 and 0.38.2 as supported versions
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-08-19 21:30:41 +02:00
dependabot[bot] baecf181ea build(deps): Bump sigstore/cosign-installer in the actions group
Bumps the actions group with 1 update: [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer).


Updates `sigstore/cosign-installer` from 3.5.0 to 3.6.0
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](https://github.com/sigstore/cosign-installer/compare/v3.5.0...v3.6.0)

---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-16 05:51:26 +02:00
Luca Guerra 342b20dc7d update(rule): update description
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-08-02 18:00:30 +02:00
Luca Guerra 1d3cd24e81 fix(incubating_rules): revert #508
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-08-02 18:00:30 +02:00
h4l0gen 068f0f2dc9 changing line length limit to 130
Signed-off-by: h4l0gen <ks3913688@gmail.com>
2024-07-18 16:08:27 +02:00
schie 28b98b6f5f fix: fixed output issues within the sandbox ruleset
Signed-off-by: Stefano Chierici <stefano.chierici@sysdig.com>

Signed-off-by: schie <77834235+darryk10@users.noreply.github.com>
2024-06-27 21:22:50 +02:00
Lorenzo Susini c0a9bf17d5 vote: update(OWNERS): add loresuso to approvers
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2024-06-12 15:29:44 +02:00
schie ea8f792589 fix: fixed output issues within the incubating ruleset
Signed-off-by: Stefano Chierici <stefano.chierici@sysdig.com>

Signed-off-by: schie <77834235+darryk10@users.noreply.github.com>
2024-06-11 20:18:40 +02:00
schie ea57e78ea1 Update falco_rules.yaml
Signed-off-by: Stefano Chierici <stefano.chierici@sysdig.com>

Signed-off-by: schie <77834235+darryk10@users.noreply.github.com>
2024-06-06 17:59:24 +02:00
Damien DELPORTE 36f4320a46 fix: Missing % in "Unexpected UDP Traffic" output rule
Signed-off-by: Damien DELPORTE <damien.delporte@doctolib.com>
2024-06-06 17:30:23 +02:00
Andrea Terzolo df963b6bcd cleanup: remove `startswith /etc`
In macro `sensitive_files` the `startswith /etc` is redundant because it
used in combination with the `in` condition

Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2024-05-31 11:59:59 +02:00
Andrea Terzolo a81590059c cleanup(falco_rules): we need only dup exit events
In `Redirect STDOUT/STDIN` rule we check for evt.rawres but this is a
parameter that we only have in the exit event

Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2024-05-31 11:59:59 +02:00
Luca Guerra ad27109fa2 chore(gha): add 0.38.0 to supported Falco versions
Signed-off-by: Luca Guerra <luca@guerra.sh>
2024-05-30 16:35:56 +02:00
schie 679a50aa5c Create OWNERS
Added myself to maintainers for rules

Signed-off-by: Stefano Chierici <stefano.chierici@sysdig.com>
2024-05-29 16:13:50 +02:00
Leonardo Grasso 9e56293b55 fix(.github/workflow): strict naming convention for changed rules files
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2024-05-22 11:42:19 +02:00
Melissa Kilby 59bf03bf74 chore: bump engine version for incubating rules
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-20 13:39:10 +02:00
Melissa Kilby 70b0d4f389 fix: add missing Mitre to rule 'Backdoored library loaded into SSHD (CVE-2024-3094)'
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-20 13:39:10 +02:00
Melissa Kilby 95c822c595 cleanup(rules): transition rule 'BPF Program Not Profiled' to maturity incubating
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-05-20 13:39:10 +02:00
Edgaras 29c41c4eed fix: change CVE-2024-3094 to match liblzma contain instead of endswith
Signed-off-by: Edgaras <edgaras@apsega.lt>
2024-05-14 11:13:45 +02:00
Andrea Terzolo 4f153f53ae fix: add `""` case for user.name
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2024-04-30 18:14:51 +02:00
Andrea Terzolo 5ad584f200 fix: add `<NA>` check
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2024-04-30 18:14:51 +02:00
Petter Reinholdtsen e65f2518b0 rule(write_etc_common): Ignore writes by etckeeper under /etc/.git/
Every time etckeeper update the git history of the content in /etc/, it update
files in /etc/.git/ (nd /etc/.etckeeper).  This trigger a warning from falco about
writes in /etc/ for every time the cron job or package update.  This change tell
the write_etc_common macro to ignore all writes under /etc/.git/ by a
process whos anchestor is etckeeper and one of the scripts called by etckeeper
to do the /etc/.git updates.

/kind bug
/kind design
/kind feature
/area rules

Signed-off-by: Petter Reinholdtsen <pere@hungry.com>
2024-04-23 11:02:17 +02:00
dependabot[bot] ec255e68f4 build(deps): Bump sigstore/cosign-installer in the actions group
Bumps the actions group with 1 update: [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer).


Updates `sigstore/cosign-installer` from 3.4.0 to 3.5.0
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](https://github.com/sigstore/cosign-installer/compare/v3.4.0...v3.5.0)

---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-04-17 10:37:52 +02:00
Lorenzo Susini 869c9a7f4d update(falco-incubating_tules.yaml): add Backdoored library loaded into SSHD rule
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2024-04-05 15:12:02 +02:00
Sean Doughty 88a40c8d9c update: add macro known_drop_and_execute_activities
Signed-off-by: Sean Doughty <sean@render.com>
2024-03-22 16:52:54 +01:00
Kapil Sharma 172d2c283f Update .github/workflows/yaml-lint.yaml
Co-authored-by: Federico Di Pierro <nierro92@gmail.com>
Signed-off-by: Kapil Sharma <ks3913688@gmail.com>
Signed-off-by: h4l0gen <ks3913688@gmail.com>
2024-03-22 15:37:53 +01:00
Kapil Sharma d7a3895155 Update .github/workflows/yaml-lint.yaml
Co-authored-by: Federico Di Pierro <nierro92@gmail.com>
Signed-off-by: Kapil Sharma <ks3913688@gmail.com>
Signed-off-by: h4l0gen <ks3913688@gmail.com>
2024-03-22 15:37:53 +01:00
Kapil Sharma 354f9ea692 Update yaml-lint.yaml
Signed-off-by: Kapil Sharma <ks3913688@gmail.com>
Signed-off-by: h4l0gen <ks3913688@gmail.com>
2024-03-22 15:37:53 +01:00
Kapil Sharma 9ba166cf44 Add files via upload
Signed-off-by: Kapil Sharma <ks3913688@gmail.com>
Signed-off-by: h4l0gen <ks3913688@gmail.com>
2024-03-22 15:37:53 +01:00
Leonardo Grasso fbf0a4e8ce update(rules): cleanup k8s.gcr.io
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2024-03-14 09:43:24 +01:00
Louis Cailliot 44addef4f7 fix: authors and required engine version
Signed-off-by: Louis Cailliot <louis.cailliot@thalesgroup.com>
2024-03-08 11:12:03 +01:00
Louis Cailliot acd08c4107 Rename falco_mitre_checker into falco_mitre_attack_checker
Signed-off-by: Louis Cailliot <louis.cailliot@thalesgroup.com>
2024-03-08 11:12:03 +01:00
Louis Cailliot f42e702682 falco rules mitre checker module
Signed-off-by: Louis Cailliot <louis.cailliot@thalesgroup.com>
2024-03-08 11:12:03 +01:00
Petter Reinholdtsen dc7970d175 update(sandbox): Added systemd to list of programs ignored when using BPF.
On Fedora 39, events like this is logged:

  Notice BPF Program  Not Profiled (bpf_cmd=5 evt_type=bpf user=root
  user_uid=0 user_loginuid=-1 process=systemd proc_exepath=/usr/lib/systemd/systemd
  parent=<NA> command=systemd --switched-root --system --deserialize=36 rhgb terminal=0
  exe_flags=<NA> container_id=host container_name=host)

This is just normal systemd behaviour, and not really interesting to log.  The provided
patch include systemd in the list of processes allowed to use BPF without any event logged.

Signed-off-by: Petter Reinholdtsen <pere@hungry.com>
2024-03-01 19:24:37 +01:00
Leonardo Grasso f88b991a7f update(.github/FALCO_VERSIONS): unsupporting 0.37
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2024-02-29 17:34:34 +01:00
RohithRaju 2ded9e2613 update(sandbox): update required_engine_version
Signed-off-by: RohithRaju <rohithraju488@gmail.com>
2024-02-29 17:31:34 +01:00
RohithRaju 623ee22a3e update(rules/sandbox_rules): update bpf cmd format
Signed-off-by: RohithRaju <rohithraju488@gmail.com>
2024-02-29 17:31:34 +01:00
dependabot[bot] b499a1d0d0 build(deps): Bump the actions group with 1 update
Bumps the actions group with 1 update: [Ana06/get-changed-files](https://github.com/ana06/get-changed-files).


Updates `Ana06/get-changed-files` from 2.2.0 to 2.3.0
- [Release notes](https://github.com/ana06/get-changed-files/releases)
- [Commits](https://github.com/ana06/get-changed-files/compare/v2.2.0...v2.3.0)

---
updated-dependencies:
- dependency-name: Ana06/get-changed-files
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-23 11:36:08 +01:00
Melissa Kilby 497e01189e chore: add Github Pages badge
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-02-13 17:22:22 +01:00
Melissa Kilby b0497d597f chore: minor readme edits
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-02-13 17:22:22 +01:00
Federico Di Pierro 34bc909603 update(ci): add Falco 0.37.1 to FALCO_VERSIONS.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-02-13 14:28:23 +01:00
dependabot[bot] 0f609769ef build(deps): Bump the actions group with 1 update
Bumps the actions group with 1 update: [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer).


Updates `sigstore/cosign-installer` from 3.3.0 to 3.4.0
- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](https://github.com/sigstore/cosign-installer/compare/v3.3.0...v3.4.0)

---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-02-10 07:18:07 +01:00
Lorenzo Susini 0afd6eace9 test: add test for rules file requirements
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2024-02-09 18:13:05 +01:00
Lorenzo Susini 8b480923cb fix: trim spaces for required_engine_version and use atoi to parse integer version in case
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2024-02-09 18:13:05 +01:00
Federico Di Pierro 6ed2036d83 fix(ci): fixed pages CI.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2024-02-09 09:56:03 +01:00
Leonardo Grasso 1053b2d1b6 ci(.github): add 0.37 to FALCO_VERSIONS
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2024-01-30 18:33:33 +01:00
Melissa Kilby 3cac61cfa9 update: add debugging advice to readme + add new links
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-01-30 15:51:32 +01:00
Melissa Kilby 3c82a97683 chore: additional historical announcements in readme and add compatible falco release badge
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-01-30 15:51:32 +01:00
Melissa Kilby 3f982327dd chore: change color of icons
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-01-30 15:51:32 +01:00
Melissa Kilby 28bb5b019e chore: add more badges to readme
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-01-30 15:51:32 +01:00
Melissa Kilby aabd1fbb6a chore: minor clarifications in docs
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-01-30 15:51:32 +01:00
Melissa Kilby 7c10902456 chore: improve language in CONTRIBUTING doc
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-01-30 15:51:32 +01:00
Melissa Kilby fd892b78af chore: CSS style in readme not supported, change it
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-01-30 15:51:32 +01:00
Melissa Kilby 3f2202d3db update(docs): new readme style to introduce rules core concepts
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-01-30 15:51:32 +01:00
Brenno Oliveira 3f668d0568 update(build/registry): allow optional auth to update-index cmd
Signed-off-by: Brenno Oliveira <brenno.oliveira@deliveryhero.com>
2024-01-29 15:25:28 +01:00
Andrea Terzolo c39d31a0bc cleanup(CI): remove no more used Falco version
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2024-01-16 12:53:51 +01:00
Andrea Terzolo c70d051893 update(rules): bump engine version to Falco 0.37.0 engine version
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2024-01-16 12:53:51 +01:00
Melissa Kilby 2ac430be13 chore: remove exe_flags= outputs fields from each non spawned_process rule
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-01-11 10:16:38 +01:00
Andrea Terzolo 1221b9e817 update(falco_rules): restore original fields
this commit restores `target=%evt.arg.oldpath linkpath=%evt.arg.newpath`
fields for the `Create Hardlink Over Sensitive Files` rule.

Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
Co-authored-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2024-01-08 18:20:29 +01:00
Andrea Terzolo 3178f6cd63 cleanup: remove `evt.arg.*` fields when always return NA
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2024-01-08 18:20:29 +01:00
Andrea Terzolo bc15f2a29d update(deprecated_rules): use SemVer `required_engine_version`
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2024-01-08 18:16:29 +01:00
dependabot[bot] 424b258789 build(deps): Bump actions/deploy-pages from 3 to 4
Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 3 to 4.
- [Release notes](https://github.com/actions/deploy-pages/releases)
- [Commits](https://github.com/actions/deploy-pages/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/deploy-pages
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-03 07:46:11 +01:00
dependabot[bot] 529b10a2a6 build(deps): Bump actions/upload-pages-artifact from 2 to 3
Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 2 to 3.
- [Release notes](https://github.com/actions/upload-pages-artifact/releases)
- [Commits](https://github.com/actions/upload-pages-artifact/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/upload-pages-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-01-03 07:45:11 +01:00
dependabot[bot] cd33bc34af build(deps): Bump actions/download-artifact from 3 to 4
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-15 23:17:49 +01:00
dependabot[bot] 195ae8297a build(deps): Bump actions/upload-artifact from 3 to 4
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-15 23:16:50 +01:00
dependabot[bot] 262f56986e build(deps): Bump the actions group with 1 update
Bumps the actions group with 1 update: [sigstore/cosign-installer](https://github.com/sigstore/cosign-installer).

- [Release notes](https://github.com/sigstore/cosign-installer/releases)
- [Commits](https://github.com/sigstore/cosign-installer/compare/v3.2.0...v3.3.0)

---
updated-dependencies:
- dependency-name: sigstore/cosign-installer
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-12 11:15:42 +01:00
dependabot[bot] dd38952168 build(deps): Bump actions/setup-go from 4 to 5
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 4 to 5.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-07 18:28:28 +01:00
dependabot[bot] 447c809fde build(deps): Bump actions/setup-python from 4 to 5
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 4 to 5.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-07 18:27:29 +01:00
dependabot[bot] eff31cab57 build(deps): Bump actions/upload-pages-artifact from 1 to 2
Bumps [actions/upload-pages-artifact](https://github.com/actions/upload-pages-artifact) from 1 to 2.
- [Release notes](https://github.com/actions/upload-pages-artifact/releases)
- [Commits](https://github.com/actions/upload-pages-artifact/compare/v1...v2)

---
updated-dependencies:
- dependency-name: actions/upload-pages-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-06 05:25:25 +01:00
dependabot[bot] abe601b7d8 build(deps): Bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-06 05:24:25 +01:00
dependabot[bot] cad89fcf17 build(deps): Bump aws-actions/configure-aws-credentials from 1 to 4
Bumps [aws-actions/configure-aws-credentials](https://github.com/aws-actions/configure-aws-credentials) from 1 to 4.
- [Release notes](https://github.com/aws-actions/configure-aws-credentials/releases)
- [Changelog](https://github.com/aws-actions/configure-aws-credentials/blob/main/CHANGELOG.md)
- [Commits](https://github.com/aws-actions/configure-aws-credentials/compare/v1...v4)

---
updated-dependencies:
- dependency-name: aws-actions/configure-aws-credentials
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-06 05:23:25 +01:00
dependabot[bot] 4423b76267 build(deps): Bump actions/setup-python from 2 to 4
Bumps [actions/setup-python](https://github.com/actions/setup-python) from 2 to 4.
- [Release notes](https://github.com/actions/setup-python/releases)
- [Commits](https://github.com/actions/setup-python/compare/v2...v4)

---
updated-dependencies:
- dependency-name: actions/setup-python
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-06 05:22:25 +01:00
dependabot[bot] 0afda1ffe1 build(deps): Bump actions/upload-artifact from 2 to 3
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 2 to 3.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v2...v3)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-06 05:20:25 +01:00
dependabot[bot] f373324498 build(deps): Bump actions/github-script from 6.4.1 to 7.0.1
Bumps [actions/github-script](https://github.com/actions/github-script) from 6.4.1 to 7.0.1.
- [Release notes](https://github.com/actions/github-script/releases)
- [Commits](https://github.com/actions/github-script/compare/v6.4.1...v7.0.1)

---
updated-dependencies:
- dependency-name: actions/github-script
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-06 05:19:25 +01:00
dependabot[bot] 448d429ae4 build(deps): Bump actions/deploy-pages from 1 to 3
Bumps [actions/deploy-pages](https://github.com/actions/deploy-pages) from 1 to 3.
- [Release notes](https://github.com/actions/deploy-pages/releases)
- [Commits](https://github.com/actions/deploy-pages/compare/v1...v3)

---
updated-dependencies:
- dependency-name: actions/deploy-pages
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-12-06 05:18:25 +01:00
dependabot[bot] 64e2adb309 build(deps): Bump actions/setup-go from 3 to 4
Bumps [actions/setup-go](https://github.com/actions/setup-go) from 3 to 4.
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](https://github.com/actions/setup-go/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/setup-go
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-13 12:24:46 +01:00
cpanato 35a379a211 bump cosign installer to v3.2.0 and use always the latest cosign
Signed-off-by: cpanato <ctadeu@gmail.com>
2023-11-10 09:18:31 +01:00
cpanato 29964b3cfa setup dependabot
Signed-off-by: cpanato <ctadeu@gmail.com>
2023-11-10 09:18:31 +01:00
Lorenzo Susini 8f0520fa09 update(rules): no need for double quoting required engine version value
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-11-07 10:36:22 +01:00
Lorenzo Susini 8e1ae009dc update(build/registry): make sure new artifacts requirements contain the new `engine_version_semver` key.
All the rules are already modified to contain a semver string

Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-11-07 10:36:22 +01:00
Richard Tweed e206c1a3f1 Update with @incertum 's suggestions
Signed-off-by: Richard Tweed <RichardoC@users.noreply.github.com>
2023-10-11 16:26:45 +02:00
Richard Tweed 177db2d421 Apply suggestions from code review
Co-authored-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
Signed-off-by: Richard Tweed <RichardoC@users.noreply.github.com>
2023-10-11 16:26:45 +02:00
Richard Tweed af9f206cce Add detection for attempt to use CVE-2023-4911
Signed-off-by: Richard Tweed <RichardoC@users.noreply.github.com>
2023-10-11 16:26:45 +02:00
Leonardo Grasso 5f42a381a7 docs(rules): add spdx identifier
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-10-11 14:58:44 +02:00
Leonardo Grasso 3a036f259f docs(build/registry): add license header
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-10-11 14:58:44 +02:00
Leonardo Grasso a5dd5a26ad docs: add spdx identifier
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-10-11 14:58:44 +02:00
Brenno Oliveira a22d0d7a41 Add parenthesis to containerd_activities macro
Signed-off-by: Brenno Oliveira <brenno.oliveira@deliveryhero.com>
2023-10-07 20:08:06 +02:00
Brenno Oliveira 82d7a935b5 Add macro dedicated to containerd activities
Signed-off-by: Brenno Oliveira <brenno.oliveira@deliveryhero.com>
2023-10-07 20:08:06 +02:00
Brenno Oliveira 93310c5328 Add container check to Clear Log Activities rule
Signed-off-by: Brenno Oliveira <brenno.oliveira@deliveryhero.com>
2023-10-07 20:08:06 +02:00
Jason Dellaluce d119706074 refactor(build/checker): avoid duplicate definitions and update to latest description format
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-09-29 17:17:22 +02:00
Jason Dellaluce 2e1aed6cb2 update(build/checker): bump falcosecurity/testing dep
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-09-29 17:17:22 +02:00
Jason Dellaluce 5f7d2e1ebc update(FALCO_VERSIONS): use v0.36.0 and master as in CI
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-09-29 17:17:22 +02:00
Jason Dellaluce 1229c908e0 fix(rules/falco-deprecated): rollback to numeric version req
Semantic versioning is supported only after engine version 0.26.0.
Using a semantic version on older version will be incompatible
with older falcos, thus defating the purposes of having < 26 version
requirement.

Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-09-29 17:17:22 +02:00
Lorenzo Susini e1bbf23ef5 update(rules): convert required engine version to new semver representation
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-09-29 01:59:21 +02:00
Lorenzo Susini c366d5bd03 new(rules): add modification to authorized keys rule
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-09-26 15:29:07 +02:00
Luca Guerra ca4b012277 update(readme): add example helm command line
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-25 20:10:05 +02:00
Luca Guerra 7a7cf24f7d new(README): add explanation about rules 2.x
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-25 17:48:05 +02:00
Luca Guerra 77ba57ab2c fix(registry): correct repository name in the signature info
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-22 10:33:48 +02:00
Luca Guerra 69c9be89d7 update(registry): add signature information for sandbox, incubating and stable rules
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-21 15:18:47 +02:00
Luca Guerra 97308654f2 update(build): add 0.36.0-rc2 in the rules
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-21 14:51:47 +02:00
Luca Guerra cafc57b6a4 update(build): update FALCO_VERSIONS in preparation for rules 2.0.0
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-21 14:51:47 +02:00
Melissa Kilby 53430cc2ed fix(rules/sandbox): update rule desc of 'Kubernetes Client Tool Launched in Container'
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-09-20 23:22:45 +02:00
Luca Guerra 6d3fcf0467 update(rules/sandbox): fix misleading name
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-20 17:04:44 +02:00
Lorenzo Susini d0b17a21cc update(rules): graduate fileless execution rule
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-09-20 11:54:44 +02:00
Melissa Kilby 13e2a4132f cleanup(rules): format unshare rule desc
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-09-20 10:11:29 +02:00
Massimiliano Giovagnoli df92bed459 deps: bump falcoctl to v0.6.1
Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
2023-09-19 21:12:28 +02:00
Massimiliano Giovagnoli bb0fb05bf6 test(index_test.go): update e2e cases with artifact signature info
Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
2023-09-19 21:12:28 +02:00
Massimiliano Giovagnoli 0ccedf8d11 feat(index.go): add signature info to the index entry from registry
Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
2023-09-19 21:12:28 +02:00
Massimiliano Giovagnoli 91b57451a3 feat(registry.go): add artifact signature to the registry model
Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
2023-09-19 21:12:28 +02:00
Melissa Kilby bea364ef41 fix(ci): formatting rules overview doc
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-09-18 14:46:48 +02:00
Melissa Kilby e88840157e new(rules): add 'Change namespace privileges via unshare'
Co-authored-by: darryk10 <stefano.chierici@sysdig.com>
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-09-18 14:44:47 +02:00
Melissa Kilby 57a272bad5 cleanup(rules): bump required engine version for sandbox rules
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-09-18 14:42:47 +02:00
Melissa Kilby 7e68da25d2 new(rules): add 'Basic Interactive Reconnaissance'
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-09-18 14:42:47 +02:00
Lorenzo Susini ee5fb38eba update(incubating rules): bump required engine version
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-09-14 14:41:43 +02:00
Lorenzo Susini 0c8e178b0a update(rules): improve fileless execution rule description and output
Co-authored-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
Signed-off-by: Lorenzo Susini <49318629+loresuso@users.noreply.github.com>
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-09-14 14:41:43 +02:00
Lorenzo Susini 0a06f07494 new(rules): add rule for detecting fileless execution
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-09-14 14:41:43 +02:00
Melissa Kilby 4e61a8cde5 cleanup(rules): graduate 'Disallowed SSH Connection Non Standard Port' to maturity_stable
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-09-14 12:54:42 +02:00
Melissa Kilby 37005e84a1 new(rules): add 'Exfiltrating Artifacts via Kubernetes Control Plane'
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-09-14 12:52:42 +02:00
Melissa Kilby 43580b4ceb new(rules): Decoding Payload in Container
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-09-12 13:10:35 +02:00
Luca Guerra 18d7045763 fix(build): update latest even if higher prereleases are present
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-12 09:58:34 +02:00
Melissa Kilby c6e01fa7a5 new(rules): add 'BPF Program Not Profiled'
Co-authored-by: Andrea Terzolo <andreaterzolo3@gmail.com>
Co-authored-by: darryk10 <stefano.chierici@sysdig.com>
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-09-11 10:44:13 +02:00
Melissa Kilby d31dbc26ea new(rules): add 'Disallowed SSH Connection Non Standard Port'
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-09-08 13:06:02 +02:00
Leonardo Grasso 5e9bafdb1c fix(.github): do not fail when no PR info found
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-09-07 13:16:59 +02:00
Leonardo Grasso b6372d2675 update: archive `application-rules`
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-09-06 11:24:59 +02:00
Leonardo Grasso a96f8213a8 docs(archive): readme for archived rules files
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-09-06 11:24:59 +02:00
Leonardo Grasso a9376d66ca build(registry): ignore "reserved" and "archived" rulesfiles
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-09-06 11:24:59 +02:00
Luca Guerra 6ed73fee78 fix(build): add registry argument
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-05 16:30:57 +02:00
Luca Guerra a2a5032613 fix(build): login with cosign upon release
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-05 16:19:57 +02:00
Luca Guerra 36f6c6638e fix(build): sign fully qualified name
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-05 16:19:57 +02:00
Luca Guerra 28d9d1fb25 update(build): output full name on push
Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-09-05 16:19:57 +02:00
Leonardo Grasso f1954372af update(registry): add incubating, sandbox, and deprecated rules files
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-09-04 21:22:52 +02:00
Melissa Kilby c3cd1c2be1 cleanup(ci): adjust rule naming in overview doc
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-09-04 21:22:52 +02:00
Leonardo Grasso d00ff32d38 update(rules): keep deprecated rules only in falco-deprecated_rules.yaml
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-09-04 21:22:52 +02:00
Leonardo Grasso 4259d0a9b2 update(rules): keep sandbox rules only in falco-sandobox_rules.yaml
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-09-04 21:22:52 +02:00
Leonardo Grasso 56268a32b6 update(rules): keep incubating rules only in falco-incubating_rules.yaml
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-09-04 21:22:52 +02:00
Leonardo Grasso 8bc186bd7c update(rules): keep stable rules only in falco_rules.yaml
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-09-04 21:22:52 +02:00
Leonardo Grasso e5ae5aa2b7 chore(rules): split falco_rules.yaml and preserve git history (step 2: rename back)
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-09-04 21:22:52 +02:00
Leonardo Grasso b611572514 chore(rules): split falco_rules.yaml and preserve git history (step 1: copy)
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-09-04 21:22:52 +02:00
Leonardo Grasso fbf7d82f0d chore(.github): upload PR info even prev jobs have failed
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-09-04 21:22:52 +02:00
Leonardo Grasso c85089fbe2 fix(.github): do not fail when previous version is non-existing
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-09-04 21:22:52 +02:00
Leonardo Grasso 63ee78a541 fix(.github): correctly handle multiple files
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-09-04 21:22:52 +02:00
Leonardo Grasso cd7584237a docs: ruleset naming convention
This stricter naming convention is required to avoid corner cases in CI and the distribution system while providing a simple guideline for contributors.

Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-09-04 21:22:52 +02:00
Melissa Kilby b42893a6eb cleanup(rules): re-balance rules and assign maturity_stable to some rules
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-31 10:10:29 +02:00
Melissa Kilby e64bad6077 cleanup(rules): consistently use exe wrt java for robustness
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-31 10:09:29 +02:00
Melissa Kilby 39214d8197 cleanup(rules): lint macro style and ensure consistency
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-31 10:09:29 +02:00
Melissa Kilby 27e6d6199a cleanup(rules): upon re-assessment move some rules to maturity_deprecated
They do not conform to rules writing best practices wrt the rules maturity framework guidelines.
They are very challenging to operationalize.

Co-authored-by: darryk10 <stefano.chierici@sysdig.com>
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-31 10:08:29 +02:00
Melissa Kilby 7a58d2848b cleanup(rules): update desc of maturity_sandbox rules + general cleanup
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-31 10:08:29 +02:00
Melissa Kilby 40a9817330 docs(README): refine rules maturity framework intro
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-29 17:29:21 +02:00
Melissa Kilby 9b0f595622 cleanup(rules): enforce style guide for existing conditions
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-29 17:29:21 +02:00
Melissa Kilby c520c50a5d cleanup(rules): fix tags for host only rules
Co-authored-by: darryk10 <stefano.chierici@sysdig.com>
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-29 17:29:21 +02:00
Melissa Kilby 56f33fe181 feat(rules): delete rule 'Delete Bash History' as suggested in comment
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-29 17:29:21 +02:00
Melissa Kilby f645bf1f76 cleanup(rules): update desc of some existing maturity_sandbox -> maturity_incubating rules according to the new style guide
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-29 12:46:21 +02:00
Melissa Kilby a3a452ac2d cleanup(rules): update desc of some existing maturity_stable rules according to the new style guide
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-29 12:46:21 +02:00
Melissa Kilby d5535fae6e cleanup(rules): update desc of some existing maturity_incubating rules according to the new style guide
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-29 12:46:21 +02:00
Melissa Kilby 479ca1a253 cleanup(ci): refine markdown based on rules maturity framework adjustments
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-29 12:38:21 +02:00
Melissa Kilby 428cf5c5b7 docs(CONTRIBUTING): refine rules maturity framework guidelines
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-29 12:38:21 +02:00
Melissa Kilby c94b62d8dc cleanup(rules): re-balance rules, bump several rules to maturity_incubating
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-29 09:04:20 +02:00
Melissa Kilby 3ceea88eeb cleanup(ci): update overview generator for multiple rules files in rules dir
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-24 09:22:39 +02:00
Massimiliano Giovagnoli bf1639a574 feat(build/registry): return built oci artifact digest
Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
2023-08-23 18:43:37 +02:00
Thomas Spear af38849954 chore(deps): Bump falcoctl in registry binary to resolve CVE-2022-1996 in indirect dependency github.com/emicklei/go-restful
Signed-off-by: Thomas Spear <tspear@conquestcyber.com>
2023-08-23 18:33:37 +02:00
Melissa Kilby 8774bcf190 cleanup(rules): update container_entrypoint (2/n)
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-23 16:55:37 +02:00
Allan Xavier 7347f6987c update(rules): comment how to reduce reverse shell detection noise
The fd.types field introduced in libs 0.12.0 allows us to improve the reverse
shell rule so it fires only once all three of stdout/stderr/stdin are
redirected.

Signed-off-by: Allan Xavier <allan.xavier@sysdig.com>
2023-08-22 22:51:27 +02:00
Melissa Kilby 64ce419d92 cleanup(rules): adjust priority for Run shell untrusted
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-17 12:57:09 +02:00
Melissa Kilby 2738eaf005 cleanup(rules): update container_entrypoint 1/n
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-08-17 12:48:08 +02:00
Andrea Terzolo b8f8df50b1 cleanup: remove `requirements.txt`
Signed-off-by: Andrea Terzolo <andreaterzolo3@gmail.com>
2023-08-08 15:55:36 +02:00
Melissa Kilby 0328c590db cleanup(rules): adjust output fields
Co-authored-by: Leonardo Grasso <me@leonardograsso.com>
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-31 18:33:09 +02:00
Melissa Kilby 91c30c786f cleanup(rules): adjust output fields wrt new style guide
https://falco.org/docs/rules/style-guide/

Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-31 18:33:09 +02:00
Melissa Kilby 12a531c4db cleanup(rules): add explanations to always_true never_true macros
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-31 18:31:09 +02:00
Melissa Kilby 7a6c27747f cleanup(rules): comment out unused macro always_true
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-31 18:31:09 +02:00
Melissa Kilby f2063bf461 fix(rules): adjust some mitre phases and codes
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-31 18:31:09 +02:00
Melissa Kilby d6fd686d38 fix(rules): correct syntax errors in disabled rules
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-31 18:31:09 +02:00
Melissa Kilby ef0e3a9e09 cleanup(ci): adjust overview generator markdown
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-27 23:44:42 +02:00
Melissa Kilby 5ac90e8f91 new(rules): initial tagging of PCI DSS related rules
https://falco.org/blog/falco-pci-controls/

Co-authored-by: nigeldouglas-itcarlow <C00292053@itcarlow.ie>
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-27 10:48:41 +02:00
Melissa Kilby 210851752b new(rules): initial tagging of NIST related rules
https://falco.org/blog/falco-nist-controls/

Co-authored-by: nigeldouglas-itcarlow <C00292053@itcarlow.ie>
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-27 10:48:41 +02:00
Melissa Kilby b4051e9976 cleanup(ci): move and update rules overview generator py script
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-27 09:17:41 +02:00
Melissa Kilby 2e24083fe0 cleanup(docs): add explicit list of useful links
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-27 09:17:41 +02:00
Melissa Kilby 9126bef2a7 cleanup(rules): initial tagging of sandbox or incubating rules round5
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-26 18:53:39 +02:00
Leonardo Grasso 342d54c0de docs(.github): update PR template according to the new contrib guide
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-07-26 17:37:38 +02:00
Melissa Kilby 5bf679d560 cleanup(docs): update readme with new overview doc link
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-26 17:21:39 +02:00
Melissa Kilby d8651ddb19 cleanup(docs): adjustments to new CONTRIBUTING
Co-authored-by: Leonardo Grasso <me@leonardograsso.com>
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-26 17:21:39 +02:00
Melissa Kilby ecdb63640e cleanup: update readme w/ new information wrt rules maturity framework and adoption
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-26 17:21:39 +02:00
Melissa Kilby 98ecbb00e7 new: add dedicated rules contributing guidelines
Based on the proposal https://github.com/falcosecurity/rules/blob/main/proposals/20230605-rules-adoption-management-maturity-framework.md

Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-26 17:21:39 +02:00
Federico Di Pierro 8ae99d0f8f chore(ci): disable Table of Content in overview page.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2023-07-26 17:17:38 +02:00
Federico Di Pierro d62eb2d057 fix(ci): properly name overview as index.md, as required by mkdocs.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2023-07-26 17:17:38 +02:00
Federico Di Pierro 54485ba9f6 fix(ci): fixed pages generation.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2023-07-26 17:06:39 +02:00
Federico Di Pierro eff69152bf new(ci): added github pages around rules overview file.
Signed-off-by: Federico Di Pierro <nierro92@gmail.com>
2023-07-26 17:00:38 +02:00
Melissa Kilby 8ea38c8af5 cleanup(rules): fix java process conditions
Java applications very often have a custom process name, therefore
proc.name or proc.pname are not well suited for rules conditions to
determine java applications, use 'proc.exe endswith java' instead,
same for proc.pexe etc.

Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-26 16:55:38 +02:00
Melissa Kilby 053c4ab2f9 cleanup(rules): initial tagging of stable rules round4
Includes:
* enhanced desc
* more complete output fields
* cleanup of tags if applicable
* add new maturity_stable tag

Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-26 16:55:38 +02:00
Melissa Kilby d1a79021ff cleanup(rules): initial tagging of sandbox or incubating rules round1
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-26 16:41:38 +02:00
Melissa Kilby 4ff9e73589 cleanup(rules): initial tagging of sandbox or incubating rules round4
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-26 15:15:38 +02:00
Melissa Kilby 8c61dd9a38 cleanup(rules): initial tagging of sandbox or incubating rules round3
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-26 15:11:39 +02:00
Melissa Kilby 6c8d40202e cleanup(rules): initial tagging of sandbox or incubating rules round2
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-26 15:09:38 +02:00
Melissa Kilby 5cea56e38a cleanup(rules): initial tagging of stable rules round3
Includes:
* enhanced desc
* more complete output fields
* cleanup of tags if applicable
* add new maturity_stable tag

Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-25 17:51:36 +02:00
Melissa Kilby eb0e3222bb cleanup(rules): initial tagging of stable rules round2
Includes:
* enhanced desc
* more complete output fields
* cleanup of tags if applicable
* add new maturity_stable tag

Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-25 09:10:35 +02:00
Melissa Kilby 0d0e333151 cleanup(rules): reduce string mismatching in 'Netcat Remote Code Execution in Container'
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-24 15:56:33 +02:00
Melissa Kilby d5f505058d cleanup(rules): initial tagging of stable rules round1
Includes:
* enhanced desc
* more complete output fields
* cleanup of tags if applicable
* add new maturity_stable tag

Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-24 15:56:33 +02:00
Jason Dellaluce a388354c94 fix(ci): solve issues with docker
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-07-21 13:05:46 +02:00
Melissa Kilby 13f1cf2292 cleanup(rules): initial transitions of some sandbox rules to incubating
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-19 09:45:36 +02:00
Massimiliano Giovagnoli b165df95f8 chore(.github/workflows/release.yaml): bump cosign
Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
2023-07-18 17:22:36 +02:00
Massimiliano Giovagnoli 5732c97229 chore(.github/workflows): remove gh deprectated functions
Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
2023-07-18 17:22:36 +02:00
Massimiliano Giovagnoli 72dbc301aa ci(release): add oci artifact signature with cosign
Signed-off-by: Massimiliano Giovagnoli <me@maxgio.it>
2023-07-18 17:22:36 +02:00
Melissa Kilby 49ade64b46 cleanup(rules): initially tag all rules disabled by default w/ maturity_sandbox level
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-14 11:14:11 +02:00
Melissa Kilby 144820c974 cleanup(proposals): clarify rules maturity framework (use tags to indicate the maturity level)
Co-authored-by: Leonardo Grasso <me@leonardograsso.com>
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-13 16:25:10 +02:00
Melissa Kilby 27e7e76cc8 cleanup(proposals): clarify rules maturity framework and rules criteria
Co-authored-by: Luca Guerra <luca@guerra.sh>
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-13 16:25:10 +02:00
Melissa Kilby 85f35284df cleanup(proposals): reference Mitre Checker Module
Co-authored-by: Louis Cailliot <louis.cailliot@thalesgroup.com>
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-13 16:25:10 +02:00
Melissa Kilby c2a8b6ca08 cleanup(proposals): adjust messaging, use new maturity and scope keys for rules categorizations
Co-authored-by: Massimiliano Giovagnoli <me@maxgio.it>
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-13 16:25:10 +02:00
Melissa Kilby 3d7e3b4ab1 cleanup(proposals): re-order paragraphs in maturity levels section
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-13 16:25:10 +02:00
Melissa Kilby 762db785ba new(proposals): formatting and editing
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-13 16:25:10 +02:00
Melissa Kilby f1a9966278 new(proposals): rules adoption, management and maturity framework
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-07-13 16:25:10 +02:00
Jason Dellaluce 4126981b6d fix(ci): adopt Ana06/get-changed-files action fork
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-07-05 17:10:32 +02:00
Jason Dellaluce e266041f4a update(ci): hold non-patch PRs on release branches
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-07-05 17:10:32 +02:00
Jason Dellaluce dc90ca5e17 chore(rules/falco_rules): trigger simple rules change
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-07-05 17:10:32 +02:00
Jason Dellaluce b362413cd0 fix(ci): improve rules version checks job
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-07-05 17:10:32 +02:00
Jason Dellaluce fec1dac8a9 update(.github): adapt workflows to new checker tool CLI options
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-07-05 17:10:32 +02:00
Jason Dellaluce dbd58845f1 chore(build/checker): make rule option explicit for validate command
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-07-05 17:10:32 +02:00
Jason Dellaluce 4e7617a528 update(build/checker): support comparing multiple rules and loading plugins
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-07-05 17:10:32 +02:00
Jason Dellaluce dd00fc25ef update(build/checker): support loading plugins for rules validation
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-07-05 17:10:32 +02:00
Kelly Birr de5a29552b Support azurefile-csi as known_aks_mount_in_privileged_containers
Signed-off-by: Kelly Birr <kelly@kellycodes.com>
2023-06-26 03:35:05 +02:00
Jason Dellaluce f5ef8d98d5 update(rules/falco_rules.yaml): add exe flags to rules with spawned process
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-19 18:48:46 +02:00
Jason Dellaluce f04755551f fix(rules/falco_rules): solve shadowing issues with `Drop and execute new binary in container`
Rule was contributed by Lorenzo Susini in https://github.com/falcosecurity/rules/pull/20.

Co-authored-by: Lorenzo Susini <susinilorenzo1@gmail.com>

Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-19 18:48:46 +02:00
Melissa Kilby a31011590d vote: update(OWNERS): add incertum (Melissa Kilby) to approvers
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-06-19 18:27:46 +02:00
Melissa Kilby c2c2f6d38a update-rules-overview-2023-06-13
Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-06-14 10:12:16 +02:00
Jason Dellaluce 32b635394c update(ci:): validate rules on every main push
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-07 16:47:43 +02:00
Jason Dellaluce f9c65cbc2a fix(ci): publish a version check comment event with no changes
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-07 16:23:43 +02:00
Jason Dellaluce e0d1d47779 docs(RELEASE.md): update versioning guidelines for patch releases
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-07 16:22:43 +02:00
Jason Dellaluce b0166d5762 chore(rules/falco_rules.yaml): remove whitespace
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-07 16:21:43 +02:00
Jason Dellaluce 0230c3c0fa update(ci): add falco v0.35 to checks
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-07 16:21:43 +02:00
Leonardo Grasso f8f7cf77a5 docs(README.md): add scope and status badges
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-06-06 16:53:40 +02:00
Jason Dellaluce 04d7b9d052 chore(rules/falco_rules.yaml): fix comment
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 20:00:18 +02:00
Jason Dellaluce 3e3dd21424 refactor(ci): rename ci.yaml in registry.yaml
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 13:18:16 +02:00
Jason Dellaluce 44cd02470c refactor(ci): separate registry and rules workflows
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 13:18:16 +02:00
Jason Dellaluce 075f79f411 chore(rules/falco_rules.yaml): fix space
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 13:18:16 +02:00
Jason Dellaluce cfd7bc4b89 fix(ci): skip rules jobs when no rule is changed
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 13:18:16 +02:00
Jason Dellaluce 0eca873f66 update(ci): fix http request body in create-comment
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 13:06:16 +02:00
Jason Dellaluce 2558e40466 fix(ci): solve issues with create-comment
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 12:37:16 +02:00
Jason Dellaluce 43e6ea781b chore(rules/falco_rules.yaml): fix space
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 12:29:16 +02:00
Jason Dellaluce c45969d9e8 docs(RELEASE.md): apply review suggestions
Co-authored-by: Leonardo Grasso <me@leonardograsso.com>
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 12:13:16 +02:00
Jason Dellaluce eb4bb8850f docs: update release guidelines
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 12:13:16 +02:00
Jason Dellaluce 4d6e63ceac update(ci): bump Falco versions to the latest compatible one
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 12:13:16 +02:00
Jason Dellaluce b943b53c14 update(ci): add safe automatic comments with GHA
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 12:13:16 +02:00
Jason Dellaluce cec94a0145 update(build/checker): print all version changes
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 12:13:16 +02:00
Jason Dellaluce b10927c410 chore(build/checker): fix typos
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 12:13:16 +02:00
Jason Dellaluce 784fbd3e1f update(build/checker): check plugin version dependencies
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 12:13:16 +02:00
Lorenzo Susini 196109384a update(checker): check increments and decrements of required_engine_version
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-06-01 12:13:16 +02:00
Lorenzo Susini 1526ec48e8 test(checker): test increments and decrements of required_engine_version
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-06-01 12:13:16 +02:00
Lorenzo Susini 9d7dc1941d update(checker): add handling of removed and added exceptions
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-06-01 12:13:16 +02:00
Jason Dellaluce b783fe4f75 chore(build/checker): improve output
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 12:13:16 +02:00
Jason Dellaluce c13b23cc19 update(ci): modularize rules validation and version check jobs
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 12:13:16 +02:00
Jason Dellaluce b96fb2347d update(ci): run build tools tests
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 12:13:16 +02:00
Jason Dellaluce 8bf47a08d8 chore: add copyright notice
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 12:13:16 +02:00
Jason Dellaluce 456ea1590c update(cmd): add tests
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 12:13:16 +02:00
Jason Dellaluce b5e9b6b5dd update(rules): bump copyright in falco rules
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 12:13:16 +02:00
Jason Dellaluce 43ce4c041a update(ci): add automatic ruleset validation and versioning suggestions
Co-authored-by: Lorenzo Susini <susinilorenzo1@gmail.com>
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 12:13:16 +02:00
Jason Dellaluce 008c6253d6 new(build): add tool for checking and validating rules files
Co-authored-by: Lorenzo Susini <susinilorenzo1@gmail.com>
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-06-01 12:13:16 +02:00
Lorenzo Susini 16fb709527 update: avoid write below etc to trigger with falcoctl
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-05-31 17:26:31 +02:00
owlinux1000 3471984e0c rule(Search Private Keys or Passwords): Add default filenames created in recent Linux to candidate for private keys
Signed-off-by: owlinux1000 <encry1024@gmail.com>
2023-05-24 16:21:06 +02:00
Brucedh afc7ff7ed2 Rule: PTRACE anti-debug attempt
Signed-off-by: Brucedh <alessandro.brucato@protonmail.com>
2023-05-24 15:42:06 +02:00
Aldo Lacuku b2290adef9 fix(registry/index): do not add artifact name to keywords if already present
The artifact name is added to the list of keywords when generating the index.yaml
file. It could happen that the list of keywords in registry.yaml already contains
the artifact name. This fix checks if the artifact name is contained in the keywords,
if not adds it

Signed-off-by: Aldo Lacuku <aldo@lacuku.eu>
2023-05-23 10:33:34 +02:00
Michael Dreher 6da15ae98c removed opencost-ui
Signed-off-by: Michael Dreher <migg@migg.net>
2023-05-17 11:11:00 +02:00
Michael Dreher b30db6a06a Adding more rules for azure AKS activities
Signed-off-by: Michael Dreher <migg@migg.net>
2023-05-17 11:11:00 +02:00
Pablo E f7735788b1 Adding conda as a package manager for Python that could be used
Signed-off-by: Pablo E <pabloem@apache.org>
2023-05-03 09:07:27 +02:00
Stefano 1bd7e4ac3a Macro(network_tool_binaries) Added netcat binary
Signed-off-by: <darryk10>stefano.chierici@sysdig.com
2023-04-06 11:28:57 +02:00
incertum 5857874e95 new(rules): comment out new umount macro
keep in rules as hint for end users

Co-authored-by: Jason Dellaluce <jasondellaluce@gmail.com>
Co-authored-by: Andrea Terzolo <andrea.terzolo@polito.it>
Signed-off-by: incertum <melissa.kilby.oss@gmail.com>
2023-04-04 17:47:53 +02:00
incertum b5e2240618 new(rules): add umount macro
Signed-off-by: incertum <melissa.kilby.oss@gmail.com>
2023-04-04 17:47:53 +02:00
incertum 8780d9d9fd cleanup(rules)!: refactor kernel module rule
Since Falco 0.35 only alert on respective syscalls (init_module, finit_module).
Deprecate alerting on spawned_process and insmod as proc.name.

Co-authored-by: Lorenzo Susini <susinilorenzo1@gmail.com>
Signed-off-by: incertum <melissa.kilby.oss@gmail.com>
2023-04-04 17:45:53 +02:00
Melissa Kilby 05d269e1e8 cleanup(rules): improve kernel module rule
A major refactor of Falco now exposes each syscall Falco's libs
supports to the end user :)

Official support starts with Falco 0.35.0

Signed-off-by: Melissa Kilby <melissa.kilby.oss@gmail.com>
2023-04-04 17:45:53 +02:00
incertum 694adf59e0 fix(rules)!: require explicit accept4 reference, overlapping syscall names deprecated
A major refactor of Falco now exposes each syscall Falco's libs
supports to the end user :)

At the same time we deprecate overlapping syscall names,
see https://github.com/falcosecurity/falco/issues/2443#issuecomment-1471289452

Official support starts with Falco 0.35.0

Co-authored-by: Jason Dellaluce <jasondellaluce@gmail.com>
Co-authored-by: Andrea Terzolo <andrea.terzolo@polito.it>
Co-authored-by: Federico Di Pierro <nierro92@gmail.com>
Signed-off-by: incertum <melissa.kilby.oss@gmail.com>
2023-04-03 10:31:39 +02:00
ch3n e0646a024f fix(rules): add authorized_server_binary list
Signed-off-by: ch3n <40637063+ch3n9w@users.noreply.github.com>
2023-03-29 18:52:31 +02:00
Lorenzo Susini 0b0f50fdf6 update: make use of contains operator in "Packet socket create in container" rule
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-03-22 15:04:07 +01:00
Lorenzo Susini 4c8e717edc Revert "update: make "Packet socket created in container" work again"
This reverts commit d59351c5fa953b3e8f3df7345d42273d120fa55a.

Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-03-22 15:04:07 +01:00
Lorenzo Susini 4f67b487e3 update: make "Packet socket created in container" work again
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-03-22 15:04:07 +01:00
Lorenzo Susini f99ffdd66a fix(rules): fix ptrace attach and injection rule
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-03-22 15:04:07 +01:00
Thomas Labarussias 3f52480618 merge the two docker_binaries into a single one, the first was overrided
Signed-off-by: Thomas Labarussias <issif+github@gadz.org>
2023-03-19 16:58:39 +01:00
Petter Reinholdtsen 61022ddbf7 Added dnf-automatic to list of rpm_binaries
The process is called by systemd regularly and write to
/var/lib/rpm/rpmdb.sqlite-shm.  This will quiet down the event log
on RHEL 9 and possibly other RHEL versions.

/kind bug
/area rules

Signed-off-by: Petter Reinholdtsen <pere@hungry.com>
2023-03-19 16:54:37 +01:00
Lorenzo Susini dab44746af update: bump required_engine_version to 16
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-03-15 12:58:50 +01:00
Lorenzo Susini a04b9aec0b update: add list of known drop and execute containers
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-03-15 12:58:50 +01:00
Lorenzo Susini 59e141b7f6 new(rules): introduce rule to detect drop and execute pattern in containers
Signed-off-by: Lorenzo Susini <susinilorenzo1@gmail.com>
2023-03-15 12:58:50 +01:00
Jason Dellaluce 83b4248807 update(falco_rules): default disable Java Process Class File Download
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-03-15 12:55:50 +01:00
Jason Dellaluce 9721907953 update(falco_rules): default disable Outbound Connection to C2 Servers
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-03-15 12:55:50 +01:00
Jason Dellaluce bb82f7d981 update(falco_rules): default disable Contact EC2 Instance Metadata Service From Container
Signed-off-by: Jason Dellaluce <jasondellaluce@gmail.com>
2023-03-15 12:55:50 +01:00
cpanato 5b6e2c0241 update k8s registry domain
Signed-off-by: cpanato <ctadeu@gmail.com>
2023-02-24 17:43:44 +01:00
Leonardo Grasso 3c1f203d84 docs(README.md): clarifications and improvements
Signed-off-by: Leonardo Grasso <me@leonardograsso.com>
2023-01-26 17:33:43 +01:00
Luca Guerra e9dc6b93f2 update(ci): use an explicit role instead of a secret
The role ARN is not a secret and does not allow any access by itself. However, adding it here explicitly makes it easier to troubleshoot potential issues.

Signed-off-by: Luca Guerra <luca@guerra.sh>
2023-01-26 09:03:40 +01:00
103 changed files with 8917 additions and 3592 deletions

4
.github/FALCO_VERSIONS vendored Normal file
View File

@ -0,0 +1,4 @@
master
0.41.2
0.41.1
0.41.0

View File

@ -1,15 +1,17 @@
<!-- Thanks for sending a pull request! Here are some tips for you:
1. If this is your first time, please read our contributor guidelines in the [CONTRIBUTING.md](https://github.com/falcosecurity/.github/blob/master/CONTRIBUTING.md) file and learn how to compile Falco from source [here](https://falco.org/docs/source).
1. This repo contains a dedicated [contributing guide](https://github.com/falcosecurity/rules/blob/main/CONTRIBUTING.md) that highlights the rules maturity framework definitions as well as the criteria for rules acceptance. Please read it carefully before submitting your PR.
2. Please label this pull request according to what type of issue you are addressing.
3. Please add a release note!
4. If the PR is unfinished while opening it specify a wip in the title before the actual title, for example, "wip: my awesome feature"
3. If the PR adds or changes one or more rules, please ensure they conform to https://falco.org/docs/rules/style-guide/ and select the appropriate maturity levels.
4. If the PR is unfinished while opening it specify a wip in the title before the actual title, for example, "wip: my awesome rule"
-->
**What type of PR is this?**
> Uncomment one (or more) `/kind <>` lines:
> /kind feature
> /kind bug
> /kind cleanup
@ -20,8 +22,6 @@
> /kind failing-test
> /kind feature
<!--
Please remove the leading whitespace before the `/kind <>` you uncommented.
@ -43,6 +43,22 @@ Please remove the leading whitespace before the `/kind <>` you uncommented.
Please remove the leading whitespace before the `/area <>` you uncommented.
-->
**Proposed rule [maturity level](https://github.com/falcosecurity/rules/blob/main/CONTRIBUTING.md#maturity-levels)**
> Uncomment one (or more) `/area <>` lines (only for PRs that add or modify rules):
> /area maturity-stable
> /area maturity-incubating
> /area maturity-sandbox
> /area maturity-deprecated
<!--
Please remove the leading whitespace before the `/area <>` you uncommented.
-->
**What this PR does / why we need it**:
**Which issue(s) this PR fixes**:
@ -50,7 +66,7 @@ Please remove the leading whitespace before the `/area <>` you uncommented.
<!--
Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
If PR is `kind/failing-tests` or `kind/flaky-test`, please post the related issues/tests in a comment and do not use `Fixes`.
If PR is `kind/failing-tests`, please post the related issues/tests in a comment and do not use `Fixes`.
-->
Fixes #

71
.github/compare-rule-files.sh vendored Executable file
View File

@ -0,0 +1,71 @@
#!/bin/bash
RULES_FILE=$1
RESULT_FILE=$2
CHECKER_TOOL=$3
FALCO_DOCKER_IMAGE=$4
set -e pipefail
rm -f $RESULT_FILE
touch $RESULT_FILE
cur_branch=`git rev-parse HEAD`
echo Current branch is \"$cur_branch\"
echo Checking version for rules file \"$RULES_FILE\"...
cp $RULES_FILE tmp_rule_file.yaml
rules_name=`echo $RULES_FILE | sed -re 's/rules\/(.*)_rules\.yaml/\1/'`
echo Searching tag with prefix prefix \"$rules_name-rules-\"...
git_rev=`git rev-list --tags="$rules_name-rules-*.*.*" --max-count=1`
if [ -z "$git_rev" ]
then
echo Not previous tag has been found
exit 0
fi
latest_tag=`git describe --match="$rules_name-rules-*.*.*" --exclude="$rules_name-rules-*.*.*-*" --abbrev=0 --tags ${git_rev} || echo ""`
if [ -z "$latest_tag" ]
then
echo Not previous tag has been found
exit 0
else
echo Most recent tag found is \"$latest_tag\"
fi
git checkout tags/$latest_tag
chmod +x $CHECKER_TOOL
$CHECKER_TOOL \
compare \
--falco-image=$FALCO_DOCKER_IMAGE \
-l $RULES_FILE \
-r tmp_rule_file.yaml \
1>tmp_res.txt
git switch --detach $cur_branch
echo '##' $(basename $RULES_FILE) >> $RESULT_FILE
echo Comparing \`$cur_branch\` with latest tag \`$latest_tag\` >> $RESULT_FILE
echo "" >> $RESULT_FILE
if [ -s tmp_res.txt ]
then
cat tmp_res.txt >> $RESULT_FILE
else
echo "No changes detected" >> $RESULT_FILE
fi
echo "" >> $RESULT_FILE
if $(git branch --show-current | grep -q "release/"); then
if $(cat $RESULT_FILE | grep -q "\*\*Minor\*\* changes") || $(cat $RESULT_FILE | grep -q "\*\*Major\*\* changes"); then
echo "**Notes**:" >> $RESULT_FILE
echo "" >> $RESULT_FILE
echo "This PR proposes merging major or minor changes into a release branch. Please make sure this is intentional. cc @falcosecurity/rules-maintainers" >> $RESULT_FILE
echo "" >> $RESULT_FILE
echo "/hold" >> $RESULT_FILE
echo "" >> $RESULT_FILE
fi
fi
rm -f tmp_rule_file.yaml
rm -f tmp_res.txt

12
.github/dependabot.yml vendored Normal file
View File

@ -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"

1
.github/scripts/.python-version vendored Normal file
View File

@ -0,0 +1 @@
3.12

11
.github/scripts/pyproject.toml vendored Normal file
View File

@ -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",
]

View File

@ -0,0 +1,160 @@
import pandas as pd
import yaml
import argparse
import datetime
import os
import sys
import re
"""
Usage:
pip install -r .github/scripts/requirements.txt
python .github/scripts/rules_overview_generator.py --rules_dir=rules > docs/index.md
"""
BASE_MITRE_URL_TECHNIQUE="https://attack.mitre.org/techniques/"
BASE_MITRE_URL_TACTIC="https://attack.mitre.org/tactics/"
BASE_PCI_DSS="https://docs-prv.pcisecuritystandards.org/PCI%20DSS/Standard/PCI-DSS-v4_0.pdf"
BASE_NIST="https://csf.tools/reference/nist-sp-800-53/r5/"
COLUMNS=['maturity', 'rule', 'desc', 'workload', 'mitre_phase', 'mitre_ttp', 'extra_tags', 'compliance_pci_dss', 'compliance_nist', 'extra_tags_list', 'mitre_phase_list', 'compliance_pci_dss_list', 'compliance_nist_list', 'enabled']
def arg_parser():
parser = argparse.ArgumentParser()
parser.add_argument('--rules_dir', help='Path to falco rules directory containing all rules yaml files.')
return parser.parse_args()
def rules_to_df(rules_dir):
l = []
for rules_filename in os.listdir(rules_dir):
if not 'falco' in rules_filename:
continue
with open(os.path.join(rules_dir, rules_filename), 'r') as f:
items = yaml.safe_load(f)
for item in items:
if 'rule' in item and 'tags' in item:
if len(item['tags']) > 0:
item['maturity'], item['workload'], item['mitre_phase'], item['mitre_ttp'], item['compliance_pci_dss'], item['compliance_nist'], item['extra_tags'] = [], [], [], [], [], [], []
for i in item['tags']:
if i.startswith('maturity_'):
item['maturity'].append(i) # should be just one per rule, be resilient and treat as list as well
elif i.startswith('PCI_DSS_'):
item['compliance_pci_dss'].append('[{}]({})'.format(i, BASE_PCI_DSS))
elif i.startswith('NIST_800-53_'):
# NIST links: revisit in the future, could be fragile
item['compliance_nist'].append('[{}]({}{}/{})'.format(i, BASE_NIST, re.search('NIST_800-53_(.*)-', i, re.IGNORECASE).group(1).lower(), \
i.replace('NIST_800-53_', '').lower()))
elif i in ['host', 'container']:
item['workload'].append(i)
elif i.startswith('mitre_'):
item['mitre_phase'].append(i)
elif i.startswith('T'):
if i.startswith('TA'):
item['mitre_ttp'].append('[{}]({}{})'.format(i, BASE_MITRE_URL_TACTIC, i.replace('.', '/')))
else:
item['mitre_ttp'].append('[{}]({}{})'.format(i, BASE_MITRE_URL_TECHNIQUE, i.replace('.', '/')))
else:
item['extra_tags'].append(i)
item['workload'].sort()
item['mitre_phase'].sort()
item['mitre_ttp'].sort()
item['compliance_pci_dss'].sort()
item['compliance_nist'].sort()
item['mitre_phase_list'] = item['mitre_phase']
item['extra_tags_list'] = item['extra_tags']
item['compliance_pci_dss_list'] = item['compliance_pci_dss']
item['compliance_nist_list'] = item['compliance_nist']
item['enabled'] = (item['enabled'] if 'enabled' in item else True)
l.append([', '.join(item[x]) if x in ['maturity', 'workload', 'mitre_phase', 'mitre_ttp', 'compliance_pci_dss', 'compliance_nist', 'extra_tags'] else item[x] for x in COLUMNS])
if not l:
sys.exit('No valid rules in any of the falco_rules.* files in the rules_dir or no falco_rules.* files in the rules_dir in the first place, exiting ...')
df = pd.DataFrame.from_records(l, columns=COLUMNS)
return df.sort_values(by=['maturity','rule'], inplace=False)
def print_markdown(df):
n_rules=len(df)
df_overview = df.drop(['extra_tags_list', 'mitre_phase_list', 'compliance_pci_dss_list', 'compliance_nist_list'], axis=1)
maturity_col_name = '<div style="width:150px">maturity</div>'
df_overview.rename(columns={ \
'maturity': maturity_col_name, \
'rule': '<div style=\"width:200px\">rule</div>', \
'desc': '<div style=\"width:450px\">desc</div>', \
'workload': '<div style=\"width:150px\">workload</div>', \
'mitre_phase': '<div style=\"width:150px\">mitre_phase</div>', \
'mitre_ttp': '<div style=\"width:150px\">mitre_ttp</div>', \
'extra_tags': '<div style=\"width:150px\">extra_tags</div>', \
'compliance_pci_dss': '<div style=\"width:150px\">compliance_pci_dss</div>', \
'compliance_nist': '<div style=\"width:150px\">compliance_nist</div>', \
'enabled': '<div style=\"width:100px\">enabled</div>', \
}, inplace=True)
df_stable = df_overview[(df_overview[maturity_col_name] == 'maturity_stable')]
df_incubating = df_overview[(df_overview[maturity_col_name] == 'maturity_incubating')]
df_sandbox = df_overview[(df_overview[maturity_col_name] == 'maturity_sandbox')]
df_deprecated = df_overview[(df_overview[maturity_col_name] == 'maturity_deprecated')]
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 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 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')
print('\n{} incubating Falco rules ({:.2f}% of rules):\n'.format(len(df_incubating), (100.0 * len(df_incubating) / n_rules)))
print(df_incubating.to_markdown(index=False))
print('\n## Sandbox Falco Rules\n')
print('\n{} sandbox Falco rules ({:.2f}% of rules):\n'.format(len(df_sandbox), (100.0 * len(df_sandbox) / n_rules)))
print(df_sandbox.to_markdown(index=False))
print('\n## Deprecated Falco Rules\n')
print('\n{} deprecated Falco rules ({:.2f}% of rules):\n'.format(len(df_deprecated), (100.0 * len(df_deprecated) / n_rules)))
print(df_deprecated.to_markdown(index=False))
print('\n# Falco Rules Stats\n')
print('\n### Falco rules per workload type:\n')
df1 = df.groupby('workload').agg(rule_count=('workload', 'count'))
df1['percentage'] = round(100.0 * df1['rule_count'] / df1['rule_count'].sum(), 2).astype(str) + '%'
print(df1.to_markdown(index=True))
print('\n### Falco rules per [Mitre Attack](https://attack.mitre.org/) phase:\n')
df2 = df[['rule', 'maturity', 'mitre_phase_list']].explode('mitre_phase_list')
df2.rename(columns={'mitre_phase_list':'mitre_phase'}, inplace=True)
df2.sort_values(by=['mitre_phase','rule'], inplace=True)
df2['rule'] = df[['maturity', 'rule']].agg(': '.join, axis=1)
mitre_phase_col_name = '<div style=\"width:200px\">mitre_phase</div>'
df2.rename(columns={'mitre_phase': mitre_phase_col_name, \
}, inplace=True)
df2 = df2.groupby(mitre_phase_col_name).agg({'rule': lambda x: ['\n'.join(list(x)), len(list(x))]})
df2['<div style=\"width:450px\">rules</div>'] = df2['rule'].apply(lambda x: x[0])
df2['<div style=\"width:100px\">percentage</div>'] = df2['rule'].apply(lambda x: round((100.0 * x[1] / n_rules), 2)).astype(str) + '%'
print(df2.drop('rule', axis=1).to_markdown(index=True))
print('\n### Compliance-related Falco rules:\n')
df3 = df
df3['compliance_tag'] = df['compliance_pci_dss_list'] + df['compliance_nist_list']
df3.sort_values(by=['rule'], inplace=True)
compliance_tag_col_name = '<div style=\"width:200px\">compliance_tag</div>'
df3.rename(columns={'compliance_tag': compliance_tag_col_name, \
}, inplace=True)
df3 = df3[['rule', compliance_tag_col_name, 'maturity']].explode(compliance_tag_col_name)
df3 = df3.groupby(compliance_tag_col_name).agg({'rule': lambda x: ['\n'.join(list(x)), len(list(x))]})
df3['<div style=\"width:450px\">rules</div>'] = df3['rule'].apply(lambda x: x[0])
# df3['percentage'] = df3['rule'].apply(lambda x: round((100.0 * x[1] / n_rules), 2)).astype(str) + '%'
print(df3.drop('rule', axis=1).to_markdown(index=True))
if __name__ == '__main__':
args_parsed = arg_parser()
rules_dir = args_parsed.rules_dir
if not rules_dir or not os.path.isdir(rules_dir):
sys.exit('No valid rules directory provided via --rules_dir arg, exiting ...')
print_markdown(rules_to_df(rules_dir))

166
.github/scripts/uv.lock vendored Normal file
View File

@ -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 },
]

6
.github/workflows/.yamllint vendored Normal file
View File

@ -0,0 +1,6 @@
extends: default
rules:
line-length:
max: 130
level: error

54
.github/workflows/create-comment.yaml vendored Normal file
View File

@ -0,0 +1,54 @@
# NOTE: This has read-write repo token and access to secrets, so this must
# not run any untrusted code.
# see: https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
name: Comment on the pull request
on:
workflow_run:
workflows: ["Rules"]
types:
- completed
jobs:
upload:
runs-on: ubuntu-latest
if: github.event.workflow_run.event == 'pull_request'
steps:
- name: 'Download artifact'
uses: actions/github-script@v7.0.1
with:
script: |
var artifacts = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: ${{github.event.workflow_run.id }},
});
var matchArtifact = artifacts.data.artifacts.filter((artifact) => {
return artifact.name == "pr"
})[0];
var download = await github.rest.actions.downloadArtifact({
owner: context.repo.owner,
repo: context.repo.repo,
artifact_id: matchArtifact.id,
archive_format: 'zip',
});
var fs = require('fs');
fs.writeFileSync('${{github.workspace}}/pr.zip', Buffer.from(download.data));
- name: 'Unpack artifact'
run: unzip pr.zip
- name: 'Comment on PR'
uses: actions/github-script@v7.0.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
var fs = require('fs');
var issue_number = Number(fs.readFileSync('./NR'));
var comment_body = fs.readFileSync('./COMMENT');
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue_number,
body: comment_body.toString('utf8')
});

43
.github/workflows/pages.yaml vendored Normal file
View File

@ -0,0 +1,43 @@
name: Deploy Github Pages
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: true
jobs:
deploy-pages:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Install uv
uses: astral-sh/setup-uv@f0ec1fc3b38f5e7cd731bb6ce540c5af426746bb # v5
- name: Generate updated inventory
run: |
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: uvx --with mkdocs-material mkdocs build
- uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3
with:
path: 'site'
- id: deployment
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4

View File

@ -1,25 +1,30 @@
name: CI
name: Registry
on:
pull_request:
branches: [main]
branches:
- main
jobs:
check-registry:
validate:
runs-on: ubuntu-latest
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'
- name: Build registry artifact tool
working-directory: build/registry
run: go build -o rules-registry ./...
- name: Test registry artifact tool
working-directory: build/registry
run: go test ./... -cover
- name: Check Registry validity
run: build/registry/rules-registry check registry.yaml

View File

@ -9,25 +9,31 @@ on:
jobs:
release-rulesfile:
runs-on: ubuntu-latest
env:
OCI_REGISTRY: ghcr.io
AWS_S3_BUCKET: falco-distribution
AWS_S3_PREFIX: rules
AWS_S3_REGION: eu-west-1
# These permissions are needed to interact with GitHub's OIDC Token endpoint.
permissions:
# These permissions are needed to interact with GitHub's OIDC Token endpoint.
id-token: write
contents: read
packages: write
steps:
- name: Checkout Rules
uses: actions/checkout@v3
# Get rules repository
- name: Checkout Rules
uses: actions/checkout@v4
# Get registry artifact tool
- name: Setup Golang
uses: actions/setup-go@v3
uses: actions/setup-go@v5
with:
go-version: '^1.19'
go-version-file: build/registry/go.mod
- name: Build registry artifact tool
working-directory: build/registry
@ -38,21 +44,34 @@ jobs:
echo "OCI_REPO_PREFIX=ghcr.io/${GITHUB_REPOSITORY,,}" >>${GITHUB_ENV}
- name: Upload OCI artifacts to GitHub packages
id: oci_build
env:
REGISTRY_USER: ${{ github.repository_owner }}
REGISTRY_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_REPO_URL: ${{ github.server_url }}/${{ github.repository }}.git
# uses OCI_REPO_PREFIX environment variable
run: build/registry/rules-registry push-to-oci registry.yaml ${{ github.ref_name }}
run: >-
echo "ARTIFACT_REPO_DIGEST=$(
build/registry/rules-registry push-to-oci registry.yaml ${{ github.ref_name }}
)" >> $GITHUB_OUTPUT
# Create a signature of the rules artifact as OCI artifact
- name: Install Cosign
uses: sigstore/cosign-installer@v3.9.0
- name: Login with cosign
run: cosign login $OCI_REGISTRY --username ${{ github.repository_owner }} --password ${{ secrets.GITHUB_TOKEN }}
- name: Sign the images with GitHub OIDC Token
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: ${{ secrets.AWS_ROLE_TO_ASSUME }}
role-to-assume: "arn:aws:iam::292999226676:role/terraform-20230120142903096000000002"
aws-region: ${{ env.AWS_S3_REGION }}
- name: Upload OCI artifacts to S3
- name: Upload files to S3
# uses AWS_S3_BUCKET, AWS_S3_PREFIX, AWS_S3_REGION environment variables
run: build/registry/rules-registry upload-to-s3 registry.yaml ${{ github.ref_name }}

195
.github/workflows/rules.yaml vendored Normal file
View File

@ -0,0 +1,195 @@
name: Rules
on:
pull_request:
branches:
- main
- release/*
push:
branches:
- main
jobs:
# retrieves the changed rules files and the Falco versions to be used
get-values:
runs-on: ubuntu-latest
outputs:
changed-files: ${{ steps.set-changed-files.outputs.changed-files }}
falco-versions: ${{ steps.set-falco-versions.outputs.versions }}
steps:
- name: Checkout rules
uses: actions/checkout@v4
- name: Get changed files
id: changed-files
if: github.event_name == 'pull_request'
uses: Ana06/get-changed-files@v2.3.0
with:
format: space-delimited
token: ${{ secrets.GITHUB_TOKEN }}
- name: Find changed rules files
id: set-changed-files
run: |
# 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/*_rules.yaml)
else
for changed_file in $all_files; do
if [[ "${changed_file}" =~ ^rules/[^/]*_rules\.yaml$ ]]; then
values=${values}${changed_file}$'\n'
fi
done
fi
echo "changed-files=$(echo "${values}" | jq -R -s -c 'split("\n")' | jq -c 'map(select(length > 0))')" >> $GITHUB_OUTPUT
- name: Read Falco versions
id: set-falco-versions
run: |
values=""
while read -r line
do
values="${values}${line}"$'\n'
done < "./.github/FALCO_VERSIONS"
echo "versions=$(echo "${values}" | jq -R -s -c 'split("\n")' | jq -c 'map(select(length > 0))')" >> $GITHUB_OUTPUT
validate:
if: needs.get-values.outputs.changed-files != '[]' && needs.get-values.outputs.changed-files != ''
needs: get-values
strategy:
fail-fast: false
matrix:
rules-file: ${{ fromJson(needs.get-values.outputs.changed-files) }}
falco-version: ${{ fromJson(needs.get-values.outputs.falco-versions) }}
runs-on: ubuntu-latest
steps:
- name: Setup Golang
uses: actions/setup-go@v5
with:
go-version: "1.19.0"
- name: Checkout rules
uses: actions/checkout@v4
- name: Build checker tool
working-directory: build/checker
run: go build -o rules-check
- name: Test checker tool
working-directory: build/checker
run: go test ./... -cover
- name: Validate rules file
run: |
build/checker/rules-check \
validate \
--falco-image="falcosecurity/falco:${{ matrix.falco-version }}" \
-r ${{ matrix.rules-file }}
check-version:
if: github.event_name == 'pull_request' && needs.get-values.outputs.changed-files != '[]' && needs.get-values.outputs.changed-files != ''
needs: get-values
env:
# note(jasondellaluce): using the most recent targeted Falco version
FALCO_VERSION: ${{ fromJson(needs.get-values.outputs.falco-versions)[0] }}
strategy:
fail-fast: false
matrix:
rules-file: ${{ fromJson(needs.get-values.outputs.changed-files) }}
runs-on: ubuntu-latest
steps:
- name: Setup Golang
uses: actions/setup-go@v5
with:
go-version: "1.19.0"
- name: Checkout rules
uses: actions/checkout@v4
- name: Get all git tags
run: git fetch --tags origin
- name: Get changed files
uses: Ana06/get-changed-files@v2.3.0
id: changed
with:
format: space-delimited
token: ${{ secrets.GITHUB_TOKEN }}
- name: Build checker tool
working-directory: build/checker
run: go build -o rules-check
- name: Test checker tool
working-directory: build/checker
run: go test ./... -cover
- name: Compare changed files with previous versions
id: compare
run: |
./.github/compare-rule-files.sh \
"${{ matrix.rules-file }}" \
result.txt \
build/checker/rules-check \
"falcosecurity/falco:$FALCO_VERSION"
if [ -s result.txt ]; then
echo "comment_file=result.txt" >> $GITHUB_OUTPUT
fi
- name: Save PR info
if: steps.compare.outputs.comment_file != ''
run: |
mkdir -p ./pr
cp ${{ steps.compare.outputs.comment_file }} ./pr/COMMENT-${{ strategy.job-index }}
- name: Upload PR info as artifact
uses: actions/upload-artifact@v4
if: steps.compare.outputs.comment_file != ''
with:
name: pr-${{ strategy.job-index }}
path: pr/
retention-days: 1
upload-pr-info:
needs: [get-values, check-version]
if: ${{ !cancelled() && github.event_name == 'pull_request' && needs.get-values.outputs.changed-files != '[]' && needs.get-values.outputs.changed-files != '' }}
runs-on: ubuntu-latest
steps:
- name: Download PR infos
uses: actions/download-artifact@v4
with:
path: tmp-artifacts
- name: Save PR info
run: |
if [ ! -d "./tmp-artifacts/" ]; then
echo "No PR info found. Skipping."
exit 0
fi
mkdir -p ./pr
echo ${{ github.event.number }} > ./pr/NR
touch ./pr/COMMENT
echo "# Rules files suggestions" >> ./pr/COMMENT
echo "" >> ./pr/COMMENT
files=$(find ./tmp-artifacts/)
for file in $files; do
if [[ "$file" =~ "COMMENT" ]]; then
cat "$file" >> ./pr/COMMENT
fi
done
echo Uploading PR info...
cat ./pr/COMMENT
echo ""
- name: Upload PR info as artifact
uses: actions/upload-artifact@v4
with:
name: pr
path: pr/
retention-days: 1
if-no-files-found: warn

19
.github/workflows/yaml-lint.yaml vendored Normal file
View File

@ -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

196
.gitignore vendored Normal file
View File

@ -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/

109
CONTRIBUTING.md Normal file
View File

@ -0,0 +1,109 @@
# Contributing
Thank you for your interest in contributing to Falco's rules!
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).
**Table of Contents**
* [Rules Maturity Framework](#rules-maturity-framework)
* [Rules Acceptance Criteria](#rules-acceptance-criteria)
# Rules Maturity Framework
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 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.
## Overall Guidelines
As specified in the tags section of the [Style Guide of Falco Rules](https://falco.org/docs/rules/style-guide/#tags), every rule upstreamed to The Falco Project must include a maturity level as its first tag.
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 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:
```
falco_rules.yaml
falco-incubating_rules.yaml
falco-sandbox_rules.yaml
falco-deprecated_rules.yaml
```
Falco offers configurability through the [falco.yaml](https://github.com/falcosecurity/falco/blob/master/falco.yaml) file, enabling support for the unique use cases of adopters. This configurability allows adopters to determine which rules should be loaded based on tags and other properties of the rules. With Falco 0.36 and beyond, it's now possible to apply multiple rules that match the same event, eliminating concerns about rule prioritization based on the "first match wins" principle.
Special note regarding *plugins* rules: The rules for different Falco [plugins](https://github.com/falcosecurity/plugins) are currently not integrated into this rules maturity framework.
## Maturity Levels
The levels:
- **maturity_stable** indicates that the rule has undergone thorough evaluation by experts with hands-on production experience. These experts have determined that the rules embody best practices and exhibit optimal robustness, making it more difficult for attackers to bypass Falco. These rules are highly relevant for addressing broader threats and are recommended for customization to specific environments if necessary. They primarily focus on universal system-level detections, such as generic reverse shells or container escapes, which establish a solid baseline for threat detection across diverse industries. This inherent bias against including more application-specific detections is due to their potential lack of broad relevance or applicability. However, to mitigate this bias, the maintainers reserve the right to make judgments on a case-by-case basis.
- **maturity_incubating** indicates that the rules address relevant threats, provide a certain level of robustness guarantee, and adhere to best practices in rule writing. Furthermore, it signifies that the rules have been identified by experts as catering to more specific use cases, which may or may not be relevant for each adopter. This category is expected to include a larger number of application-specific rules.
- **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.
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
A rules maturity framework has been introduced for Falco users to facilitate the adoption of non-custom rules more effectively. This framework ensures a smooth transition for adopters, whether they use rules generically or for specific use cases. A smooth adoption process is defined by making it easy for adopters to understand each rule and also gain an understanding of not just what the rule is doing, but also how beneficial it can be under various circumstances.
Additionally, due to this framework, adopters should find themselves with a clearer understanding of which rules can likely be adopted as-is versus which rules may require significant engineering efforts to evaluate and adopt.
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 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 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 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 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:
- Each rule aligns with the project's best interests as per our [governance](https://github.com/falcosecurity/evolution/blob/main/GOVERNANCE.md).
- 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` 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*
As part of the review process, the following aspects will be thoroughly checked to effectively enforce the [Style Guide of Falco Rules](https://falco.org/docs/rules/style-guide/).
- 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, 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. Lastly, The Falco Project favors broader rules over narrow ones addressing a single, less common CVE for an application.
*Relevance*
Determining relevance is often the most subjective criterion, as it requires expertise in offensive security, cyber defense, and real-world production settings for accurate assessment. Questions such as whether these threats are a priority for most organizations or if we can provide enough context for a security analyst to appropriately act on the alerts as part of their incident response workflows are top of mind when assessing the overall relevance. Relevance is a key factor that indirectly reflects both robustness and significance, but more importantly, it indicates whether a particular security threat is significant to most adopters and, consequently, beneficial to broadly detect.
Here are some aspects that can be discussed during the review process in order to decide if a rule has the potential to be effectively operationalized by most adopters:
- Cover relevant attack vectors across various industries.
- 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.

2
OWNERS
View File

@ -5,6 +5,7 @@ approvers:
- fededp
- andreagit97
- lucaguerra
- ekoops
reviewers:
- leodido
- kaizhe
@ -12,3 +13,4 @@ reviewers:
- loresuso
emeritus_approvers:
- kaizhe
- incertum

102
README.md
View File

@ -1,14 +1,72 @@
# Falco Rules
[![License](https://img.shields.io/github/license/falcosecurity/rules?style=for-the-badge)](./LICENSE)
[![Latest release](https://img.shields.io/github/v/release/falcosecurity/rules?label=Latest%20Rules%20Release&style=for-the-badge)](https://github.com/falcosecurity/rules/releases/latest) [![Compatible Falco release](https://img.shields.io/github/v/release/falcosecurity/falco?label=Compatible%20Falco%20Release&style=for-the-badge)](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).*
[![Docs](https://img.shields.io/badge/docs-latest-green.svg?style=for-the-badge)](https://falco.org/docs/rules) [![Rules Overview](https://img.shields.io/badge/docs-latest-green.svg?label=Rules%20Overview&style=for-the-badge)](https://falcosecurity.github.io/rules/) [![Style Guide](https://img.shields.io/badge/docs-latest-green.svg?label=Style%20Guide&style=for-the-badge)](https://falco.org/docs/rules/style-guide/)
This repository contains the [Rule Registry](#rule-registry) and the [rules officially maintained](#falcusecurity-rules) by the Falcosecurity organization. [Rules](https://falco.org/docs/rules) tell [Falco](https://github.com/falcosecurity/falco) what to do. Please refer to the [official documentation](https://falco.org/docs/rules) to better understand the rules' concepts.
[![Supported Fields](https://img.shields.io/badge/docs-latest-green.svg?label=Supported%20Fields&style=for-the-badge)](https://falco.org/docs/reference/rules/supported-fields/) [![Supported EVT ARG Fields](https://img.shields.io/badge/docs-latest-green.svg?label=Supported%20Evt%20Arg%20Fields&style=for-the-badge)](https://github.com/falcosecurity/libs/blob/master/driver/event_table.c)
## Rule Registry
[![Falco Core Repository](https://github.com/falcosecurity/evolution/blob/main/repos/badges/falco-core-blue.svg)](https://github.com/falcosecurity/evolution/blob/main/REPOSITORIES.md#core-scope) [![Stable](https://img.shields.io/badge/status-stable-brightgreen?style=for-the-badge)](https://github.com/falcosecurity/evolution/blob/main/REPOSITORIES.md#stable) [![License](https://img.shields.io/github/license/falcosecurity/rules?style=for-the-badge)](./LICENSE) [![Github Pages](https://github.com/falcosecurity/rules/actions/workflows/pages.yaml/badge.svg)](https://falcosecurity.github.io/rules/)
The Registry contains metadata and information about every rule known and recognized by the Falcosecurity organization. These rules are developed for Falco and made available to the community. <!-- Check out the sections below to know how to [register your rules](#registering-a-new-rule) and see rules currently contained in the registry. -->
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.
</br>
<p align="left">
<img src="docs/images/start.png" alt="Image" width="21" height="21">&nbsp;&nbsp;
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>
<p align="left">
<img src="docs/images/insight.png" alt="Image" width="18" height="24">&nbsp;&nbsp;
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>
<p align="left">
<img src="docs/images/setting.png" alt="Image" width="23" height="23">&nbsp;&nbsp;
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>
<p align="left">
<img src="docs/images/announce.png" alt="Image" width="20" height="20">&nbsp;&nbsp;
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>
<p align="left">
<img src="docs/images/cross.png" alt="Image" width="20" height="20">&nbsp;&nbsp;
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">&nbsp;&nbsp;
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 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](https://github.com/falcosecurity/plugins) repository._
### Naming Convention
Rule files must be located in the [/rules](rules) folder of this repository and are named according to the following convention: `<ruleset>_rules.yaml`.
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](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.
Note: _This convention applies to this repository only. Falco application does not impose any naming convention for naming rule files._
<!-- Check out the sections below to know how to [register your rules](#registering-a-new-rule) and see rules currently contained in the registry. -->
<!--
### Registering a new Rules file
@ -40,23 +98,43 @@ You can find the full registry specification here: *(coming soon...)*
### Registered Rules
Please refer to the automatically generated [rules_inventory/rules_overview.md](https://github.com/falcosecurity/rules/blob/main/rules_inventory/rules_overview.md#falco-rules---detailed-overview) file for a detailed list of all the rules currently registered.
Please refer to the automatically generated [rules overview](https://falcosecurity.github.io/rules/overview/) document file for a detailed list of all the rules currently registered.
-->
## Hosted Rules
## Falco Rules 2.x
Another purpose of this repository is to host and maintain the rules owned by the Falcosecurity organization. All the rules are contained inside the [rules](https://github.com/falcosecurity/rules/tree/main/rules) folder.
Since version 2.0.0, the rules distributed from this repository have been split into three parts:
The `main` branch contains the most up-to-date state of development. Please check our [Release Process](./RELEASE.md) to know how rules are released. Stable builds are released and published only when a new release gets tagged.
- [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.
If you wish to contribute your rules to the Falcosecurity organization, you just need to open a Pull Request to add them inside the `rules` folder. In order to be hosted in this repository, rules must be licensed under the [Apache 2.0 License](./LICENSE).
## Contributing
If you want to help and wish to contribute, please review our [contribution guidelines](https://github.com/falcosecurity/.github/blob/master/CONTRIBUTING.md). Code contributions are always encouraged and welcome!
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).

View File

@ -6,30 +6,73 @@ Official Falcosecurity rules releases are automated using GitHub Actions. Each r
In this repo, each ruleset is a standalone YAML file in the `/rules` directory (e.g. `falco_rules.yaml`, `application_rules.yaml`, ...). Each ruleset is released and versioned individually. When we release a ruleset, we do the following process:
1. Determine a new version for the given ruleset (see the [section below](#versioning-a-ruleset))
2. Create a new Git tag with the name convention `*name*-rules-*version*` (e.g. `falco-rules-0.1.0`, `application-rules-0.1.0`, ...). The naming convention is required due to this repository being a [monorepo](https://en.wikipedia.org/wiki/Monorepo) and in order to be machine-readable.
3. A GitHub action will validate the repository [registry](./registry.yaml) and release the new OCI artifact in the packages of this repository
1. Make sure that the `./github/FALCO_VERSIONS` file contains the most recent versions of Falco with which the given ruleset validates successfully.
- When releasing a ruleset, the versions must be explicit stable Falco releases (e.g. not using `latest` or `master`), so that the new tag will provide an history of the Falco versions on which the ruleset was tested
- If the ruleset does not validate with a stable Falco release (it can happen close to the time of a Falco release), it's ok to use a `master` version, which however needs to be patched with an additional commit [on the ruleset's release branch](#patching-a-ruleset) once the next stable Falco release gets published.
2. Determine a new version for the given ruleset (see the [section below](#versioning-a-ruleset)).
3. Create a new Git tag with the name convention `*name*-rules-*version*` (e.g. `falco-rules-0.1.0`, `application-rules-0.1.0`, ...). The naming convention is required due to this repository being a [monorepo](https://en.wikipedia.org/wiki/Monorepo) and in order to be machine-readable.
4. A GitHub action will validate the repository [registry](./registry.yaml) and release the new OCI artifact in the packages of this repository.
## Patching a ruleset
Patches on an already-released ruleset can anytime on a per-need basis. Assuming a release Git tag in the form of `*name*-rules-*version*`, with version being in the form of `X.Y.Z` (e.g. `falco-rules-0.1.0`), the process is as follows:
1. If not already created, create a release branch starting from the first tag of the released ruleset.
a. Checkout the first ruleset release tag: e.g. `git checkout falco-rules-0.1.0`
b. Create a new branch with the naming convention `release/*name*-rules-X.Y.x`, starting from the tag: e.g. `git checkout -b release/falco-rules-0.1.x`
c. As for step #1 of the [*Releasing a ruleset section*](#releasing-a-ruleset), make sure that `./github/FALCO_VERSIONS` contains all the **stable** Falco versions with which the ruleset validates successfully, by adding an extra commit to the release branch in case changes are required.
d. Open a [PR in falcosecurity/test-infra](https://github.com/falcosecurity/test-infra/edit/master/config/config.yaml) to add `release/*name*-rules-X.Y.x` as protected branch to the `prow/config.yaml`, for example:
```yaml
rules:
branches:
main:
protect: true
...
"release/falco-rules-0.1.x":
protect: true
```
2. Open one or more PRs agains the release branch of the released ruleset.
a. Wait for all the CI checks to pass.
b. Check the automatic versioning suggestions provided by the CI (see [an example](https://github.com/falcosecurity/rules/pull/74#issuecomment-1571867580)), and make sure that **only patch changes** are present.
c. Considering the automatic versioning suggestions, and at discretion of the domain knowledge of the repository maintainers, decide whether the PR should be merged or not.
3. Bump the ruleset version **patch** number by 1 and create a new Git tag from the release branch (e.g. `falco-rules-0.1.1`).
4. A GitHub action will validate the repository [registry](./registry.yaml) and release the new OCI artifact in the packages of this repository.
## Versioning a ruleset
The version of the official Falco rulesets is compatible with [SemVer](https://semver.org/) and must be meaningful towards the changes in its structure and contents. To define a new version `x.y.z` for a given ruleset, consider the following guidelines.
Our automation will detect most of the following criteria and suggest a summary with all the changes relative to each of the three versioning categories (patch, minor, major). This provides a changelog and valuable suggestion on the next version to be assigned to each ruleset. However, be mindful that the versioning process cannot totally automated and always requires human attention (e.g. we can't automatically detect subtle semantic changes in rules). The automated jobs will use the versions of Falco defined in `./github/FALCO_VERSIONS` for validating and checking rulesets. The versions must be line-separated and ordered from the most recent to the least recent. Any [published container image tag](https://hub.docker.com/r/falcosecurity/falco/tags) is a valid Falco version entry, including `master`, `latest`, and any other stable release tag (e.g. `0.35.0`). `master` indicates the most recent dev version of Falco built from mainline, and can be used for using a not-yet-published version of Falco in case we want to run the CI with a new in-development feature.
**NOTE:** *The versioning guidelines also apply to any versioned ruleset not maintained in this repository (such as the ones in [falcosecurity/plugins](https://github.com/falcosecurity/plugins)), including the ones distributed by third parties. These are best practices that guarantee the correct behavior of Falco when updating a given ruleset to a new version.*
- `z` _(patch number)_ is incremented when you make backward-compatible changes. In this case, the ruleset can be updated in a given Falco without needing to update Falco, its plugins, or its configuration. Examples:
- Decrementing `required_engine_version`
- Decrementing plugin version requirement in `required_plugin_versions`
- Adding alternatives entries to an already-existing plugin version requirement in `required_plugin_versions`
- Removing a plugin version requirement with all its alternatives in `required_plugin_versions`
- Enabling at default one or more rules that used to be disabled
- Adding or removing items for one or more lists
- Adding or removing exceptions for one or more Falco rules (without needing a `required_engine_version`)
- Changing the condition for one or more rules or macros by still preserving their logical security scope (e.g. making them less noisy)
- Adding one or more tags to a rule
- Increasing the priority of a rule
- Changing the output fields of a rule (without increasing `required_engine_version`)
- Adding or removing exceptions for one or more Falco rules (without increasing `required_engine_version`)
- Changing the condition for one or more rules by still preserving their logical security scope (e.g. making them less noisy, matching more events than before)
- `y` _(minor number)_ is incremented when you add functionality in a backward-compatible manner. In order to be accepted, the new ruleset may mandate updating the version of Falco, changing its configuration, or updating/installing one or more plugins. Examples:
- Incrementing the `required_engine_version` number
- Incrementing `required_engine_version`
- Incrementing the `required_plugin_versions` version requirement for one or more plugin
- Adding a new plugin version requirement in `required_plugin_versions`
- Adding a new plugin version requirement (with or without `alternatives`) in `required_plugin_versions`
- Adding one or more lists, macros, or rules
- Adapting the ruleset to a Falco engine version introducing *backward-compatible* changes in the expected ruleset language definitions or file format. For now, this can't happen without also bumping `required_engine_version` since it is a simple progressive number. However, this may change in the future if we consider adopting a sem-ver-like version scheme.
- `x` _(major number)_ is incremented when you make incompatible content changes which change the expected behavior and outcome of the ruleset. Incompatibilities may arise when relying on the ruleset from other rulesets (e.g. appending conditions or overriding the definition of a list, macro, or rule). Examples:
- Removing a plugin version requirement alternative (without removing the whole dependency) in `required_plugin_versions`
- Renaming or removing a list, macro, or rule
- Changing the event source of a rule
- Disabling at default one or more rules that used to be enabled
- Changing the logical security scope of one or more lists, macros, or rules (e.g. a rule stops detecting an entire spectrum of events that it used to detect, or starts serving a substantially different purpose)
- Adapting the ruleset to a Falco engine version introducing backward-incompatible changes in the expected ruleset language definitions or file format
- Removing one or more tags from a rule
- Decreasing the priority of a rule
- Changing in any way the set of matched events matched by a macro
- Changing the logical security scope of one or more macros or rules (e.g. a rule starts serving a substantially different purpose, or matches less events than before)
- Adapting the ruleset to a Falco engine version introducing *backward-incompatible* changes in the expected ruleset language definitions or file format
When more than one version numbers need to be incremented, the most dominant takes precedence. For example, incrementing the `z` patch number would be enough when minorly chaning a rule's condition to make it less noisy, however you must increment the `y` minor number in case the new condition uses a new field or operator that requires increasing the `required_engine_version`.

7
archive/README.md Normal file
View File

@ -0,0 +1,7 @@
# Archived Rules Files
This directory hosts archived rules files. While they are preserved for historical purposes or as examples, please note the following:
- These files are **no longer maintained**.
- There's a possibility that they may **not function correctly**.
- They are **not recommended for use in production environments**.

View File

@ -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
build/checker/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
checker

View File

@ -0,0 +1,98 @@
// 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 cmd
import (
"fmt"
"math"
"strings"
)
const defaultFalcoDockerImage = "falcosecurity/falco:master"
const defaultFalcoDockerEntrypoint = "/usr/bin/falco"
var falcoPriorities = []string{
"emergency",
"alert",
"critical",
"error",
"warning",
"notice",
"informational", // or "info"
"debug",
}
// compareInt returns 1 if "left" is greater than right,
// -1 if "right" is greater than left, and 0 otherwise.
func compareInt(a, b int) int {
if a == b {
return 0
}
if a < b {
return -1
}
return 1
}
// compareFalcoPriorities returns 1 if "left" is more urgent than right,
// -1 if "right" is more urgent than left, and 0 otherwise.
func compareFalcoPriorities(left, right string) int {
lIndex := math.MaxInt
rIndex := math.MaxInt
for i, p := range falcoPriorities {
if strings.HasPrefix(p, strings.ToLower(left)) {
lIndex = i
}
if strings.HasPrefix(p, strings.ToLower(right)) {
rIndex = i
}
}
return compareInt(rIndex, lIndex)
}
// errAppend returns an error resulting froma appending two errors.
func errAppend(left, right error) error {
if left == nil {
return right
}
if right == nil {
return left
}
return fmt.Errorf("%s, %s", left.Error(), right.Error())
}
// strSliceToMap returns a map[string]bool (a set, basically) from a strings slice.
func strSliceToMap(s []string) map[string]bool {
items := make(map[string]bool)
for _, item := range s {
items[item] = true
}
return items
}
// diffStrSet returns a map[string]bool containing all the strings present
// in left but without the strings present in right.
func diffStrSet(left, right []string) map[string]bool {
l := strSliceToMap(left)
r := strSliceToMap(right)
for k := range r {
delete(l, k)
}
return l
}

View File

@ -0,0 +1,55 @@
// 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 cmd
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestCompareInt(t *testing.T) {
t.Parallel()
assert.Equal(t, -1, compareInt(1, 2))
assert.Equal(t, -1, compareInt(1, 5))
assert.Equal(t, 0, compareInt(5, 5))
assert.Equal(t, 1, compareInt(6, 5))
assert.Equal(t, 1, compareInt(10, 5))
}
func TestCompareFalcoPriorities(t *testing.T) {
t.Parallel()
assert.Equal(t, -1, compareFalcoPriorities("debug", "info"))
assert.Equal(t, 1, compareFalcoPriorities("info", "debug"))
assert.Equal(t, 0, compareFalcoPriorities("info", "informational"))
}
func TestDiffStrSet(t *testing.T) {
t.Parallel()
a := []string{"a", "b", "c"}
b := []string{"b", "d"}
d1 := diffStrSet(a, b)
assert.Len(t, d1, 2)
assert.Contains(t, d1, "a")
assert.Contains(t, d1, "c")
d2 := diffStrSet(b, a)
assert.Len(t, d2, 1)
assert.Contains(t, d2, "d")
}

View File

@ -0,0 +1,468 @@
// 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 cmd
import (
"encoding/json"
"fmt"
"strconv"
"github.com/blang/semver"
"github.com/falcosecurity/testing/pkg/falco"
"github.com/falcosecurity/testing/pkg/run"
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
func getVerRequirement(f *falco.PluginVersionRequirementDescription, pluginName string) *falco.PluginVersionRequirement {
if f.Name == pluginName {
return &f.PluginVersionRequirement
}
for _, a := range f.Alternatives {
if a.Name == pluginName {
return &a
}
}
return nil
}
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
}
func findPluginVerRequirement(f *falco.RulesetDescription, pluginName string) *falco.PluginVersionRequirementDescription {
for _, r := range f.RequiredPluginVersions {
req := getVerRequirement(&r, pluginName)
if req != nil {
return &r
}
}
return nil
}
func listNames(f *falco.RulesetDescription) []string {
var names []string
for _, l := range f.Lists {
names = append(names, l.Info.Name)
}
return names
}
func macroNames(f *falco.RulesetDescription) []string {
var names []string
for _, l := range f.Macros {
names = append(names, l.Info.Name)
}
return names
}
func ruleNames(f *falco.RulesetDescription) []string {
var names []string
for _, l := range f.Rules {
names = append(names, l.Info.Name)
}
return names
}
func getCompareOutput(falcoImage, configFile string, ruleFiles, extraFiles []string) (*falco.RulesetDescription, error) {
testOptions := []falco.TestOption{
falco.WithOutputJSON(),
falco.WithOutputJSON(),
falco.WithArgs("-L"),
}
for _, rf := range ruleFiles {
f := run.NewLocalFileAccessor(rf, rf)
testOptions = append(testOptions, falco.WithRules(f))
}
if len(configFile) > 0 {
f := run.NewLocalFileAccessor(configFile, configFile)
testOptions = append(testOptions, falco.WithConfig(f))
}
for _, ef := range extraFiles {
f := run.NewLocalFileAccessor(ef, ef)
testOptions = append(testOptions, falco.WithExtraFiles(f))
}
// run falco and collect/print validation issues
runner, err := run.NewDockerRunner(falcoImage, defaultFalcoDockerEntrypoint, nil)
if err != nil {
return nil, err
}
res := falco.Test(runner, testOptions...)
// collect errors
err = errAppend(err, res.Err())
if res.ExitCode() != 0 {
err = errAppend(err, fmt.Errorf("unexpected exit code (%d)", res.ExitCode()))
}
// unmarshal json output
var out falco.RulesetDescription
err = json.Unmarshal(([]byte)(res.Stdout()), &out)
if err != nil {
logrus.Info(res.Stderr())
return nil, err
}
if err != nil {
return nil, err
}
return &out, nil
}
func compareRulesPatch(left, right *falco.RulesetDescription) (res []string) {
// Decrementing required_engine_version
lRequiredEngineVersion, _ := strconv.Atoi(left.RequiredEngineVersion)
rRequiredEngineVersion, _ := strconv.Atoi(right.RequiredEngineVersion)
if compareInt(lRequiredEngineVersion, rRequiredEngineVersion) > 0 {
res = append(res, fmt.Sprintf("Required engine version was decremented from %s to %s",
left.RequiredEngineVersion, right.RequiredEngineVersion))
}
// Remove or decrement plugin version requirement
for _, lpr := range left.RequiredPluginVersions {
var tmpRemoveRes []string
lpReqs := getRequirements(&lpr)
for _, lr := range lpReqs {
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(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))
}
}
}
if len(tmpRemoveRes) == len(lpReqs) {
res = append(res, tmpRemoveRes...)
}
}
// Adding plugin version requirement alternative
for _, rpr := range right.RequiredPluginVersions {
var lrl *falco.PluginVersionRequirementDescription
rReqs := getRequirements(&rpr)
for _, rreq := range rReqs {
lrl = findPluginVerRequirement(left, rreq.Name)
if lrl != nil {
break
}
}
if lrl != nil {
for _, rreq := range rReqs {
if getVerRequirement(lrl, rreq.Name) == nil {
res = append(res, fmt.Sprintf("Version dependency alternative to plugin `%s` has added", rreq.Name))
}
}
}
}
for _, l := range left.Rules {
for _, r := range right.Rules {
if l.Info.Name == r.Info.Name {
// Enabling at default one or more rules that used to be disabled
if !l.Info.Enabled && r.Info.Enabled {
res = append(res, fmt.Sprintf("Rule `%s` has been enabled at default", l.Info.Name))
}
// Matching more events in a rule condition
if len(diffStrSet(r.Details.Events, l.Details.Events)) > 0 {
res = append(res, fmt.Sprintf("Rule `%s` matches more events than before", l.Info.Name))
}
// A rule has different output fields
if compareInt(len(l.Details.OutputFields), len(r.Details.OutputFields)) != 0 {
res = append(res, fmt.Sprintf("Rule `%s` changed its output fields", l.Info.Name))
}
// A rule has more tags than before
if len(diffStrSet(r.Info.Tags, l.Info.Tags)) > 0 {
res = append(res, fmt.Sprintf("Rule `%s` has more tags than before", l.Info.Name))
}
// A rule's priority becomes more urgent than before
if compareFalcoPriorities(r.Info.Priority, l.Info.Priority) > 0 {
res = append(res, fmt.Sprintf("Rule `%s` has a more urgent priority than before", l.Info.Name))
}
// Adding or removing exceptions for one or more Falco rules
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))
}
}
}
}
for _, l := range left.Lists {
for _, r := range right.Lists {
if l.Info.Name == r.Info.Name {
// Adding or removing items for one or more lists
if len(diffStrSet(l.Info.Items, r.Info.Items)) != 0 ||
len(diffStrSet(r.Info.Items, l.Info.Items)) != 0 {
res = append(res, fmt.Sprintf("List `%s` has some item added or removed", l.Info.Name))
}
}
}
}
return
}
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)
if compareInt(l_required_engine_version, r_required_engine_version) < 0 {
res = append(res, fmt.Sprintf("Required engine version was incremented from %s to %s",
left.RequiredEngineVersion, right.RequiredEngineVersion))
}
// Adding a new plugin version requirement in required_plugin_versions
for _, rpr := range right.RequiredPluginVersions {
var lrl *falco.PluginVersionRequirementDescription
rReqs := getRequirements(&rpr)
for _, rreq := range rReqs {
lrl = findPluginVerRequirement(left, rreq.Name)
if lrl != nil {
break
}
}
if lrl == nil {
res = append(res, fmt.Sprintf("Version dependency to plugin `%s` has added", rpr.Name))
}
}
// Incrementing the version requirement for one or more plugin
for _, lpr := range left.RequiredPluginVersions {
lpReqs := getRequirements(&lpr)
for _, lr := range lpReqs {
rr := findPluginVerRequirement(right, lr.Name)
if rr != nil {
lv := semver.MustParse(lr.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))
}
}
}
}
// Adding one or more lists, macros, or rules
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(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(listNames(right), listNames(left))
if len(diff) > 0 {
for v := range diff {
res = append(res, fmt.Sprintf("List `%s` has been added", v))
}
}
return
}
func compareRulesMajor(left, right *falco.RulesetDescription) (res []string) {
// Remove plugin version requirement alternative
for _, lpr := range left.RequiredPluginVersions {
var tmpRes []string
lpReqs := getRequirements(&lpr)
for _, lr := range lpReqs {
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))
}
}
// it's not a breaking change to remove a whole plugin dependency block
if len(tmpRes) < len(lpReqs) {
res = append(res, tmpRes...)
}
}
// Renaming or removing a list, macro, or rule
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(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(listNames(left), listNames(right))
if len(diff) > 0 {
for v := range diff {
res = append(res, fmt.Sprintf("List `%s` has been removed", v))
}
}
for _, l := range left.Rules {
for _, r := range right.Rules {
if l.Info.Name == r.Info.Name {
// Rule has a different source
if l.Info.Source != r.Info.Source {
res = append(res, fmt.Sprintf("Rule `%s` has different source (before='%s', after='%s')", l.Info.Name, l.Info.Source, r.Info.Source))
}
// Disabling at default one or more rules that used to be enabled
if l.Info.Enabled && !r.Info.Enabled {
res = append(res, fmt.Sprintf("Rule `%s` has been disabled at default", l.Info.Name))
}
// Matching less events in a rule condition
if len(diffStrSet(l.Details.Events, r.Details.Events)) > 0 {
res = append(res, fmt.Sprintf("Rule `%s` matches less events than before", l.Info.Name))
}
// A rule has less tags than before
if len(diffStrSet(l.Info.Tags, r.Info.Tags)) > 0 {
res = append(res, fmt.Sprintf("Rule `%s` has less tags than before", l.Info.Name))
}
// a priority becomes less urgent than before
if compareFalcoPriorities(l.Info.Priority, r.Info.Priority) > 0 {
res = append(res, fmt.Sprintf("Rule `%s` has a less urgent priority than before", l.Info.Name))
}
}
}
}
for _, l := range left.Macros {
for _, r := range right.Macros {
if l.Info.Name == r.Info.Name {
// Matching different events in a macro condition
if len(diffStrSet(l.Details.Events, r.Details.Events)) > 0 ||
len(diffStrSet(r.Details.Events, l.Details.Events)) > 0 {
res = append(res, fmt.Sprintf("Macro `%s` matches different events than before", l.Info.Name))
}
}
}
}
return
}
var compareCmd = &cobra.Command{
Use: "compare",
// todo: load more than one rules files both on left and right
Short: "Compare two rules files and suggest version changes",
RunE: func(cmd *cobra.Command, args []string) error {
leftRules, err := cmd.Flags().GetStringArray("left")
if err != nil {
return err
}
rightRules, err := cmd.Flags().GetStringArray("right")
if err != nil {
return err
}
if len(leftRules) == 0 || len(rightRules) == 0 {
return fmt.Errorf("you must specify at least one rules file for both the left-hand and right-hand sides of comparison")
}
falcoImage, err := cmd.Flags().GetString("falco-image")
if err != nil {
return err
}
falcoConfigPath, err := cmd.Flags().GetString("config")
if err != nil {
return err
}
falcoFilesPaths, err := cmd.Flags().GetStringArray("file")
if err != nil {
return err
}
leftOutput, err := getCompareOutput(falcoImage, falcoConfigPath, leftRules, falcoFilesPaths)
if err != nil {
return err
}
rightOutput, err := getCompareOutput(falcoImage, falcoConfigPath, rightRules, falcoFilesPaths)
if err != nil {
return err
}
diff := compareRulesMajor(leftOutput, rightOutput)
if len(diff) > 0 {
fmt.Fprintln(cmd.OutOrStdout(), "**Major** changes:")
for _, s := range diff {
fmt.Fprintln(cmd.OutOrStdout(), "* "+s)
}
fmt.Fprintln(cmd.OutOrStdout())
}
diff = compareRulesMinor(leftOutput, rightOutput)
if len(diff) > 0 {
fmt.Fprintln(cmd.OutOrStdout(), "**Minor** changes:")
for _, s := range diff {
fmt.Fprintln(cmd.OutOrStdout(), "* "+s)
}
fmt.Fprintln(cmd.OutOrStdout())
}
diff = compareRulesPatch(leftOutput, rightOutput)
if len(diff) > 0 {
fmt.Fprintln(cmd.OutOrStdout(), "**Patch** changes:")
for _, s := range diff {
fmt.Fprintln(cmd.OutOrStdout(), "* "+s)
}
fmt.Fprintln(cmd.OutOrStdout())
}
return nil
},
}
func init() {
compareCmd.Flags().StringP("falco-image", "i", defaultFalcoDockerImage, "Docker image of Falco to be used for validation")
compareCmd.Flags().StringP("config", "c", "", "Config file to be used for running Falco")
compareCmd.Flags().StringArrayP("file", "f", []string{}, "Extra files required by Falco for running")
compareCmd.Flags().StringArrayP("left", "l", []string{}, "Rules files to be loaded for the left-hand side of the comparison")
compareCmd.Flags().StringArrayP("right", "r", []string{}, "Rules files to be loaded for the right-hand side of the comparison")
rootCmd.AddCommand(compareCmd)
}

View File

@ -0,0 +1,422 @@
// 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 cmd
import (
"encoding/json"
"testing"
"github.com/falcosecurity/testing/pkg/falco"
"github.com/stretchr/testify/assert"
)
const sampleFalcoCompareOutput = `{
"lists": [
{
"details": {
"lists": []
},
"info": {
"items": ["ash", "bash"],
"name": "list1"
}
}
],
"macros": [
{
"details": {
"condition_fields": ["fd.num","evt.type"],
"events": ["openat2","openat","open"],
"lists": [],
"macros": [],
"operators": [">=","=","in"]
},
"info": {
"name": "macro1"
}
}
],
"required_engine_version": "13",
"required_plugin_versions": [
{
"alternatives": [
{
"name": "k8saudit-eks",
"version": "0.2.0"
}
],
"name": "k8saudit",
"version": "0.6.0"
},
{
"name": "json",
"version": "0.7.0"
}
],
"rules": [
{
"details": {
"condition_fields": [],
"events": ["execve", "openat"],
"exceptions" : [],
"exception_fields": [],
"exception_operators": [],
"lists": [],
"macros": [],
"operators": [],
"output_fields": ["user.name","container.id"]
},
"info": {
"enabled": false,
"name": "rule1",
"priority": "Notice",
"source": "syscall",
"tags": ["container","network"]
}
}
]
}`
func testGetSampleFalcoCompareOutput(t *testing.T) *falco.RulesetDescription {
var out falco.RulesetDescription
err := json.Unmarshal(([]byte)(sampleFalcoCompareOutput), &out)
if err != nil {
t.Fatal(err.Error())
}
return &out
}
func TestCompareRulesPatch(t *testing.T) {
t.Parallel()
t.Run("decrement-required-engine-version", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.RequiredEngineVersion = "0"
res := compareRulesPatch(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("remove-plugin-version-requirement", func(t *testing.T) {
t.Parallel()
t.Run("with-alternatives", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.RequiredPluginVersions = o2.RequiredPluginVersions[1:]
res := compareRulesPatch(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 2)
})
t.Run("with-no-alternatives", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.RequiredPluginVersions = o2.RequiredPluginVersions[:1]
res := compareRulesPatch(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
})
t.Run("add-plugin-version-requirement-alternative", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
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)
})
t.Run("change-list", func(t *testing.T) {
t.Parallel()
t.Run("add-item", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.Lists[0].Info.Items = append(o2.Lists[0].Info.Items, "some_value")
res := compareRulesPatch(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("remove-item", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.Lists[0].Info.Items = []string{}
res := compareRulesPatch(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
})
t.Run("change-rule", func(t *testing.T) {
t.Parallel()
t.Run("enable", func(t *testing.T) {
t.Parallel()
o1 := testGetSampleFalcoCompareOutput(t)
o2 := testGetSampleFalcoCompareOutput(t)
o1.Rules[0].Info.Enabled = false
o2.Rules[0].Info.Enabled = true
res := compareRulesPatch(o1, o2)
assert.Len(t, res, 1)
})
t.Run("add-events", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.Rules[0].Details.Events = append(o2.Rules[0].Details.Events, "pluginevent")
res := compareRulesPatch(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("add-tags", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.Rules[0].Info.Tags = append(o2.Rules[0].Info.Tags, "some_other_tag")
res := compareRulesPatch(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("remove-output-field", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.Rules[0].Details.OutputFields = []string{}
res := compareRulesPatch(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("add-output-field", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.Rules[0].Details.OutputFields = append(o2.Rules[0].Details.OutputFields, "some.otherfield")
res := compareRulesPatch(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("greater-priority", func(t *testing.T) {
t.Parallel()
o1 := testGetSampleFalcoCompareOutput(t)
o2 := testGetSampleFalcoCompareOutput(t)
o1.Rules[0].Info.Priority = "DEBUG"
o2.Rules[0].Info.Priority = "INFO"
res := compareRulesPatch(o1, o2)
assert.Len(t, res, 1)
})
t.Run("add-exceptions", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.Rules[0].Details.ExceptionNames = append(o2.Rules[0].Details.ExceptionNames, "some-exception-name")
res := compareRulesPatch(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("remove-exceptions", func(t *testing.T) {
t.Parallel()
o1 := testGetSampleFalcoCompareOutput(t)
o2 := testGetSampleFalcoCompareOutput(t)
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)
})
})
}
func TestCompareRulesMinor(t *testing.T) {
t.Parallel()
t.Run("increment-required-engine-version", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.RequiredEngineVersion = "100"
res := compareRulesMinor(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("add-plugin-version-requirement", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
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)
assert.Len(t, res, 1)
})
t.Run("increment-plugin-version-requirement", func(t *testing.T) {
t.Parallel()
t.Run("of alternative", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.RequiredPluginVersions[0].Alternatives[0].Version = "10.0.0"
res := compareRulesMinor(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("of main requirement", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.RequiredPluginVersions[1].Version = "10.0.0"
res := compareRulesMinor(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
})
t.Run("add-list", func(t *testing.T) {
t.Parallel()
l := falco.ListDescription{}
l.Info.Name = "l2"
o2 := testGetSampleFalcoCompareOutput(t)
o2.Lists = append(o2.Lists, l)
res := compareRulesMinor(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("add-macro", func(t *testing.T) {
t.Parallel()
l := falco.MacroDescription{}
l.Info.Name = "m2"
o2 := testGetSampleFalcoCompareOutput(t)
o2.Macros = append(o2.Macros, l)
res := compareRulesMinor(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("add-rule", func(t *testing.T) {
t.Parallel()
l := falco.RuleDescription{}
l.Info.Name = "r2"
o2 := testGetSampleFalcoCompareOutput(t)
o2.Rules = append(o2.Rules, l)
res := compareRulesMinor(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("add-all", func(t *testing.T) {
t.Parallel()
l := falco.ListDescription{}
l.Info.Name = "l2"
m := falco.MacroDescription{}
m.Info.Name = "m2"
r := falco.RuleDescription{}
r.Info.Name = "r2"
o2 := testGetSampleFalcoCompareOutput(t)
o2.Lists = append(o2.Lists, l)
o2.Macros = append(o2.Macros, m)
o2.Rules = append(o2.Rules, r)
res := compareRulesMinor(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 3)
})
}
func TestCompareRulesMajor(t *testing.T) {
t.Parallel()
t.Run("remove-plugin-version-requirement", func(t *testing.T) {
t.Parallel()
t.Run("with-alternatives", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.RequiredPluginVersions[0].Alternatives = []falco.PluginVersionRequirement{}
res := compareRulesMajor(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
})
t.Run("remove-list", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.Lists = []falco.ListDescription{}
res := compareRulesMajor(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("remove-macro", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.Macros = []falco.MacroDescription{}
res := compareRulesMajor(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("remove-rule", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.Rules = []falco.RuleDescription{}
res := compareRulesMajor(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("remove-all", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.Lists = []falco.ListDescription{}
o2.Macros = []falco.MacroDescription{}
o2.Rules = []falco.RuleDescription{}
res := compareRulesMajor(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 3)
})
t.Run("change-macro", func(t *testing.T) {
t.Parallel()
t.Run("add-events", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.Macros[0].Details.Events = append(o2.Macros[0].Details.Events, "pluginevent")
res := compareRulesMajor(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("remove-events", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.Macros[0].Details.Events = []string{}
res := compareRulesMajor(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
})
t.Run("change-rule", func(t *testing.T) {
t.Parallel()
t.Run("change-source", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.Rules[0].Info.Source = "some_other_source"
res := compareRulesMajor(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("disable", func(t *testing.T) {
t.Parallel()
o1 := testGetSampleFalcoCompareOutput(t)
o2 := testGetSampleFalcoCompareOutput(t)
o1.Rules[0].Info.Enabled = true
o2.Rules[0].Info.Enabled = false
res := compareRulesMajor(o1, o2)
assert.Len(t, res, 1)
})
t.Run("remove-events", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.Rules[0].Details.Events = []string{}
res := compareRulesMajor(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("remove-tags", func(t *testing.T) {
t.Parallel()
o2 := testGetSampleFalcoCompareOutput(t)
o2.Rules[0].Info.Tags = []string{}
res := compareRulesMajor(testGetSampleFalcoCompareOutput(t), o2)
assert.Len(t, res, 1)
})
t.Run("lower-priority", func(t *testing.T) {
t.Parallel()
o1 := testGetSampleFalcoCompareOutput(t)
o2 := testGetSampleFalcoCompareOutput(t)
o1.Rules[0].Info.Priority = "INFO"
o2.Rules[0].Info.Priority = "DEBUG"
res := compareRulesMajor(o1, o2)
assert.Len(t, res, 1)
})
})
}

35
build/checker/cmd/root.go Normal file
View File

@ -0,0 +1,35 @@
// 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 cmd
import (
"github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command{
Use: "checker",
Short: "General-purpose tool for sanity checks around Falco rules files",
Long: "",
}
// Execute adds all child commands to the root command.
func Execute() {
logrus.SetLevel(logrus.DebugLevel)
cobra.CheckErr(rootCmd.Execute())
}

View File

@ -0,0 +1,114 @@
// 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 cmd
import (
"fmt"
"github.com/falcosecurity/testing/pkg/falco"
"github.com/falcosecurity/testing/pkg/run"
"github.com/spf13/cobra"
)
var validateCmd = &cobra.Command{
Use: "validate",
Short: "Validate one or more rules file with a given Falco version",
RunE: func(cmd *cobra.Command, args []string) error {
falcoImage, err := cmd.Flags().GetString("falco-image")
if err != nil {
return err
}
rulesFilesPaths, err := cmd.Flags().GetStringArray("rule")
if err != nil {
return err
}
if len(rulesFilesPaths) == 0 {
return fmt.Errorf("you must specify at least one rules file")
}
var ruleFiles []run.FileAccessor
for _, rf := range rulesFilesPaths {
f := run.NewLocalFileAccessor(rf, rf)
ruleFiles = append(ruleFiles, f)
}
falcoTestOptions := []falco.TestOption{
falco.WithOutputJSON(),
falco.WithRulesValidation(ruleFiles...),
}
falcoConfigPath, err := cmd.Flags().GetString("config")
if err != nil {
return err
}
if len(falcoConfigPath) > 0 {
config := run.NewLocalFileAccessor(falcoConfigPath, falcoConfigPath)
falcoTestOptions = append(falcoTestOptions, falco.WithConfig(config))
}
falcoFilesPaths, err := cmd.Flags().GetStringArray("file")
if err != nil {
return err
}
if len(falcoFilesPaths) > 0 {
for _, path := range falcoFilesPaths {
file := run.NewLocalFileAccessor(path, path)
falcoTestOptions = append(falcoTestOptions, falco.WithExtraFiles(file))
}
}
// run falco and collect/print validation issues
runner, err := run.NewDockerRunner(falcoImage, defaultFalcoDockerEntrypoint, nil)
if err != nil {
return err
}
res := falco.Test(runner, falcoTestOptions...)
if res.RuleValidation() == nil {
err = errAppend(err, fmt.Errorf("rules validation command failed"))
} else {
for _, r := range res.RuleValidation().Results {
if !r.Successful || len(r.Errors) > 0 || len(r.Warnings) > 0 {
err = errAppend(err, fmt.Errorf("rules validation had warning or errors"))
fmt.Fprintln(cmd.OutOrStdout(), res.Stdout())
break
}
}
}
// collect errors
err = errAppend(err, res.Err())
if res.ExitCode() != 0 {
err = errAppend(err, fmt.Errorf("unexpected exit code (%d)", res.ExitCode()))
}
if err != nil {
fmt.Fprintln(cmd.ErrOrStderr(), res.Stderr())
}
return err
},
}
func init() {
validateCmd.Flags().StringP("falco-image", "i", defaultFalcoDockerImage, "Docker image of Falco to be used for validation")
validateCmd.Flags().StringP("config", "c", "", "Config file to be used for running Falco")
validateCmd.Flags().StringArrayP("file", "f", []string{}, "Extra files required by Falco for running")
validateCmd.Flags().StringArrayP("rule", "r", []string{}, "Rules files to be validated by Falco")
rootCmd.AddCommand(validateCmd)
}

35
build/checker/go.mod Normal file
View File

@ -0,0 +1,35 @@
module checker
go 1.19
require (
github.com/blang/semver v3.5.1+incompatible
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
)
require (
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
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 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
github.com/google/go-cmp v0.5.9 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/net v0.7.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/tools v0.1.12 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

98
build/checker/go.sum Normal file
View File

@ -0,0 +1,98 @@
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0=
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
github.com/Microsoft/go-winio v0.6.0 h1:slsWYD/zyx7lCXoZVlvQrj0hPTM1HI4+v1sIda2yDvg=
github.com/Microsoft/go-winio v0.6.0/go.mod h1:cTAf44im0RAYeL23bpB+fzCyDH2MJiz2BO69KH/soAE=
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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 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-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=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/moby/term v0.0.0-20221205130635-1aeaba878587 h1:HfkjXDfhgVaN5rmueG8cL8KKeFNecRCXFhaJ2qZ5SKA=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM=
github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0=
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=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=

24
build/checker/main.go Normal file
View File

@ -0,0 +1,24 @@
// 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 "checker/cmd"
func main() {
cmd.Execute()
}

View File

@ -0,0 +1 @@
3.10.12

View File

@ -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.
+=======================================================================================================+
```

View File

@ -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/"

View File

@ -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()

View File

@ -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

View File

@ -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()

View File

@ -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)

View File

@ -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)

View File

@ -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]

View File

@ -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)

View File

@ -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

View File

@ -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]

View File

@ -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

View 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']

View File

@ -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']

View File

@ -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 ]

View File

@ -0,0 +1,2 @@
test: True
falco-rules: false

View File

@ -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())

View File

@ -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)

View File

@ -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)

View File

@ -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"

823
build/mitre_attack_checker/poetry.lock generated Normal file
View File

@ -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"

View File

@ -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"

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
@ -86,7 +87,7 @@ func doUploadToS3(registryFilename, gitTag string) error {
rulesfileInfo := reg.RulesfileByName(pt.Name)
if rulesfileInfo == nil {
return fmt.Errorf("could not find rulesfile %s in registry", pt.Name)
return fmt.Errorf("could not find rulesfile %s in the registry (reserved or archived are ignored)", pt.Name)
}
tmpDir, err := os.MkdirTemp("", "falco-artifacts-to-upload")
@ -109,29 +110,29 @@ func doUploadToS3(registryFilename, gitTag string) error {
return nil
}
func doPushToOCI(registryFilename, gitTag string) error {
func doPushToOCI(registryFilename, gitTag string) (*string, error) {
var ociRepoPrefix, repoGit, user, token string
var found bool
if token, found = os.LookupEnv(RegistryTokenEnv); !found {
return fmt.Errorf("environment variable with key %q not found, please set it before running this tool", RegistryTokenEnv)
return nil, fmt.Errorf("environment variable with key %q not found, please set it before running this tool", RegistryTokenEnv)
}
if user, found = os.LookupEnv(RegistryUserEnv); !found {
return fmt.Errorf("environment variable with key %q not found, please set it before running this tool", RegistryUserEnv)
return nil, fmt.Errorf("environment variable with key %q not found, please set it before running this tool", RegistryUserEnv)
}
if ociRepoPrefix, found = os.LookupEnv(OCIRepoPrefixEnv); !found {
return fmt.Errorf("environment variable with key %q not found, please set it before running this tool", OCIRepoPrefixEnv)
return nil, fmt.Errorf("environment variable with key %q not found, please set it before running this tool", OCIRepoPrefixEnv)
}
if repoGit, found = os.LookupEnv(RepoGithubEnv); !found {
return fmt.Errorf("environment variable with key %q not found, please set it before running this tool", RepoGithubEnv)
return nil, fmt.Errorf("environment variable with key %q not found, please set it before running this tool", RepoGithubEnv)
}
pt, err := parseGitTag(gitTag)
if err != nil {
return err
return nil, err
}
cred := &auth.Credential{
@ -144,18 +145,18 @@ func doPushToOCI(registryFilename, gitTag string) error {
reg, err := loadRegistryFromFile(registryFilename)
if err != nil {
return fmt.Errorf("could not read registry from %s: %w", registryFilename, err)
return nil, fmt.Errorf("could not read registry from %s: %w", registryFilename, err)
}
rulesfileInfo := reg.RulesfileByName(pt.Name)
if rulesfileInfo == nil {
return fmt.Errorf("could not find rulesfile %s in registry", pt.Name)
return nil, fmt.Errorf("could not find rulesfile %s in the registry (reserved or archived are ignored)", pt.Name)
}
// Create the repository object for the ref.
var repo *repository.Repository
if repo, err = repository.NewRepository(ociRepoRef, repository.WithClient(client)); err != nil {
return fmt.Errorf("unable to create repository for ref %q: %w", ociRepoRef, err)
return nil, fmt.Errorf("unable to create repository for ref %q: %w", ociRepoRef, err)
}
existingTags, _ := repo.Tags(context.Background())
@ -171,25 +172,45 @@ func doPushToOCI(registryFilename, gitTag string) error {
tgzFile := filepath.Join(tmpDir, filepath.Base(rulesfileInfo.Path)+".tar.gz")
if err = tarGzSingleFile(tgzFile, rulesfileInfo.Path); err != nil {
return fmt.Errorf("could not compress %s: %w", rulesfileInfo.Path, err)
return nil, fmt.Errorf("could not compress %s: %w", rulesfileInfo.Path, err)
}
defer os.RemoveAll(tgzFile)
config, err := rulesfileConfig(rulesfileInfo.Name, pt.Version(), rulesfileInfo.Path)
if err != nil {
return fmt.Errorf("could not generate configuration layer for rulesfiles %q: %w", rulesfileInfo.Path, err)
}
if err = pushCompressedRulesfile(client, tgzFile, ociRepoRef, repoGit, tagsToUpdate, config); err != nil {
return fmt.Errorf("could not push %s to %s with source %s and tags %v: %w", tgzFile, ociRepoRef, repoGit, tagsToUpdate, err)
return nil, fmt.Errorf("could not generate configuration layer for rulesfiles %q: %w", rulesfileInfo.Path, err)
}
return nil
digest, err := pushCompressedRulesfile(client, tgzFile, ociRepoRef, repoGit, tagsToUpdate, config)
if err != nil {
return nil, fmt.Errorf("could not push %s to %s with source %s and tags %v: %w", tgzFile, ociRepoRef, repoGit, tagsToUpdate, err)
}
// ociRepoDigest is a string that looks like ghcr.io/falcosecurity/rules/falco-rules@sha256:123456...
ociRepoDigest := fmt.Sprintf("%s@%s", ociRepoRef, *digest)
return &ociRepoDigest, nil
}
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 {
@ -249,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 {
@ -263,7 +284,13 @@ func main() {
Args: cobra.ExactArgs(2),
DisableFlagsInUseLine: true,
RunE: func(c *cobra.Command, args []string) error {
return doPushToOCI(args[0], args[1])
ociRepoDigest, err := doPushToOCI(args[0], args[1])
if err != nil {
return err
}
fmt.Println(*ociRepoDigest)
return nil
},
}

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.

View File

@ -1,103 +1,71 @@
module registry
go 1.19
go 1.21
toolchain go1.21.0
require (
github.com/aws/aws-sdk-go v1.44.183
github.com/aws/aws-sdk-go v1.44.288
github.com/blang/semver v3.5.1+incompatible
github.com/falcosecurity/falcoctl v0.3.0-rc5
github.com/spf13/cobra v1.6.1
github.com/stretchr/testify v1.7.2
github.com/falcosecurity/falcoctl v0.6.1
github.com/spf13/cobra v1.7.0
github.com/stretchr/testify v1.8.4
gopkg.in/yaml.v2 v2.4.0
k8s.io/klog/v2 v2.80.1
oras.land/oras-go/v2 v2.0.0-rc.3
k8s.io/klog/v2 v2.100.1
oras.land/oras-go/v2 v2.2.1
)
require (
atomicgo.dev/cursor v0.1.1 // indirect
atomicgo.dev/keyboard v0.2.8 // indirect
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
github.com/MakeNowJust/heredoc v0.0.0-20170808103936-bb23615498cd // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/chai2010/gettext-go v0.0.0-20160711120539-c6fed771bfd5 // indirect
atomicgo.dev/cursor v0.2.0 // indirect
atomicgo.dev/keyboard v0.2.9 // indirect
atomicgo.dev/schedule v0.1.0 // indirect
cloud.google.com/go/compute v1.23.0 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
github.com/containerd/console v1.0.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/cli v20.10.17+incompatible // indirect
github.com/docker/docker v20.10.17+incompatible // indirect
github.com/docker/docker-credential-helpers v0.6.4 // indirect
github.com/emicklei/go-restful v2.9.5+incompatible // indirect
github.com/evanphx/json-patch v4.12.0+incompatible // indirect
github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
github.com/go-errors/errors v1.0.1 // indirect
github.com/go-logr/logr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.19.5 // indirect
github.com/go-openapi/swag v0.19.14 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/btree v1.0.1 // indirect
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
github.com/google/uuid v1.2.0 // indirect
github.com/gookit/color v1.5.0 // indirect
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
github.com/imdario/mergo v0.3.12 // indirect
github.com/inconshreveable/mousetrap v1.0.1 // indirect
github.com/docker/cli v24.0.5+incompatible // indirect
github.com/docker/docker v24.0.5+incompatible // indirect
github.com/docker/docker-credential-helpers v0.8.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/gookit/color v1.5.4 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
github.com/lithammer/fuzzysearch v1.1.5 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/mattn/go-runewidth v0.0.13 // indirect
github.com/mitchellh/go-wordwrap v1.0.0 // indirect
github.com/moby/spdystream v0.2.0 // indirect
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/opencontainers/distribution-spec/specs-go v0.0.0-20220620172159-4ab4752c3b86 // indirect
github.com/lithammer/fuzzysearch v1.1.8 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-runewidth v0.0.15 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
github.com/oras-project/artifacts-spec v1.0.0-rc.2 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/opencontainers/image-spec v1.1.0-rc4 // indirect
github.com/oras-project/oras-credentials-go v0.3.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.9 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/pterm/pterm v0.12.45 // indirect
github.com/rivo/uniseg v0.2.0 // indirect
github.com/russross/blackfriday v1.5.2 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/pterm/pterm v0.12.67 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/spf13/afero v1.9.5 // indirect
github.com/spf13/cast v1.5.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/xlab/treeprint v0.0.0-20181112141820-a009c3971eca // indirect
github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
golang.org/x/net v0.2.0 // indirect
golang.org/x/oauth2 v0.2.0 // indirect
golang.org/x/sync v0.0.0-20220907140024-f12130a52804 // indirect
golang.org/x/sys v0.2.0 // indirect
golang.org/x/term v0.2.0 // indirect
golang.org/x/text v0.4.0 // indirect
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
github.com/spf13/viper v1.16.0 // indirect
github.com/subosito/gotenv v1.6.0 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
golang.org/x/exp v0.0.0-20230817173708-d852ddb80c63 // indirect
golang.org/x/net v0.14.0 // indirect
golang.org/x/oauth2 v0.11.0 // indirect
golang.org/x/sync v0.3.0 // indirect
golang.org/x/sys v0.11.0 // indirect
golang.org/x/term v0.11.0 // indirect
golang.org/x/text v0.12.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
google.golang.org/protobuf v1.31.0 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.4.0 // indirect
k8s.io/api v0.24.3 // indirect
k8s.io/apimachinery v0.24.3 // indirect
k8s.io/cli-runtime v0.24.3 // indirect
k8s.io/client-go v0.24.3 // indirect
k8s.io/component-base v0.24.3 // indirect
k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 // indirect
k8s.io/kubectl v0.24.3 // indirect
k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect
sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect
sigs.k8s.io/kustomize/api v0.11.4 // indirect
sigs.k8s.io/kustomize/kyaml v0.13.6 // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.1 // indirect
sigs.k8s.io/yaml v1.2.0 // indirect
gotest.tools/v3 v3.5.0 // indirect
)

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
@ -20,7 +21,7 @@ import (
"path/filepath"
"strings"
"github.com/falcosecurity/falcoctl/pkg/index"
"github.com/falcosecurity/falcoctl/pkg/index/index"
"github.com/falcosecurity/falcoctl/pkg/oci"
)
@ -36,10 +37,11 @@ func pluginRulesToIndexEntry(rf Rulesfile, registry, repo string) *index.Entry {
Repository: repo,
Description: rf.Description,
Home: rf.URL,
Keywords: append(rf.Keywords, rf.Name),
Keywords: appendIfNotPresent(rf.Keywords, rf.Name),
License: rf.License,
Maintainers: rf.Maintainers,
Sources: []string{rf.URL},
Signature: rf.Signature,
}
}
@ -69,3 +71,16 @@ func upsertIndexFile(r *Registry, ociArtifacts map[string]string, indexPath stri
return i.Write(indexPath)
}
// Add new item to a slice if not present.
func appendIfNotPresent(keywords []string, kw string) []string {
// If the keyword already exist do nothing.
for i := range keywords {
if keywords[i] == kw {
return keywords
}
}
// Add the keyword
return append(keywords, kw)
}

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
@ -20,7 +21,7 @@ import (
"reflect"
"testing"
"github.com/falcosecurity/falcoctl/pkg/index"
"github.com/falcosecurity/falcoctl/pkg/index/index"
"github.com/stretchr/testify/assert"
)
@ -32,11 +33,25 @@ func Test_upsertIndex(t *testing.T) {
indexPath string
expectedIndexPath string
}{
{"missing", "testdata/registry.yaml", map[string]string{"falco": "ghcr.io/falcosecurity/rules/falco"}, "testdata/index1.yaml", "testdata/index_expected1.yaml"},
{"already_present", "testdata/registry.yaml", map[string]string{"falco": "ghcr.io/falcosecurity/rules/falco"}, "testdata/index2.yaml", "testdata/index2.yaml"},
{
"missing",
"testdata/registry.yaml",
map[string]string{"falco": "ghcr.io/falcosecurity/rules/falco"},
"testdata/index1.yaml",
"testdata/index_expected1.yaml",
},
{
"already_present",
"testdata/registry.yaml",
map[string]string{"falco": "ghcr.io/falcosecurity/rules/falco"},
"testdata/index2.yaml",
"testdata/index2.yaml",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
i := index.New(GHOrg)
assert.NoError(t, i.Read(tt.indexPath))
expectedIndex := index.New(GHOrg)
@ -48,8 +63,25 @@ func Test_upsertIndex(t *testing.T) {
upsertIndex(r, tt.ociArtifacts, i)
if !reflect.DeepEqual(i, expectedIndex) {
t.Errorf("index() = %v, want %v", i, expectedIndex)
t.Errorf("index() = %#v, want %v", i, expectedIndex)
}
})
}
}
func TestPluginRulesToIndexEntrySignature(t *testing.T) {
t.Parallel()
signature := &index.Signature{
Cosign: &index.CosignSignature{},
}
expected := signature
p := Rulesfile{Signature: signature}
entry := pluginRulesToIndexEntry(p, "", "")
if !reflect.DeepEqual(entry.Signature, expected) {
t.Fatalf("Index entry signature: expected %#v, got %v", expected, entry.Signature)
}
}

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
@ -27,19 +28,25 @@ import (
ocipusher "github.com/falcosecurity/falcoctl/pkg/oci/pusher"
)
func pushCompressedRulesfile(ociClient remote.Client, filePath, repoRef, repoGit string, tags []string, config *oci.ArtifactConfig) error {
// pushCompressedRulesfile publishes rulesfile as OCI artifact and returns its digest.
// It possibly returns an error.
func pushCompressedRulesfile(
ociClient remote.Client,
filePath, repoRef, repoGit string,
tags []string,
config *oci.ArtifactConfig) (*string, error) {
klog.Infof("Processing compressed rulesfile %q for repo %q and tags %s...", filePath, repoRef, tags)
pusher := ocipusher.NewPusher(ociClient, false, nil)
_, err := pusher.Push(context.Background(), oci.Rulesfile, repoRef,
artifact, err := pusher.Push(context.Background(), oci.Rulesfile, repoRef,
ocipusher.WithTags(tags...),
ocipusher.WithFilepaths([]string{filePath}),
ocipusher.WithAnnotationSource(repoGit),
ocipusher.WithArtifactConfig(*config))
if err != nil {
return fmt.Errorf("an error occurred while pushing: %w", err)
return nil, fmt.Errorf("an error occurred while pushing: %w", err)
}
return nil
return &artifact.Digest, nil
}

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
@ -21,6 +22,7 @@ import (
"os"
"regexp"
"github.com/falcosecurity/falcoctl/pkg/index/index"
"gopkg.in/yaml.v2"
)
@ -37,11 +39,13 @@ type Rulesfile struct {
Email string `yaml:"email"`
Name string `yaml:"name"`
} `yaml:"maintainers"`
Keywords []string `yaml:"keywords"`
Path string `yaml:"path"`
URL string `yaml:"url"`
License string `yaml:"license"`
Reserved bool `yaml:"reserved"`
Keywords []string `yaml:"keywords"`
Path string `yaml:"path"`
URL string `yaml:"url"`
License string `yaml:"license"`
Reserved bool `yaml:"reserved"`
Archived bool `yaml:"archived"`
Signature *index.Signature `yaml:"signature,omitempty"`
}
type Registry struct {
@ -67,6 +71,9 @@ func (r *Registry) Validate() error {
// RulesfileByName returns the rulesfile in the index with the specified name, or nil if not found
func (r *Registry) RulesfileByName(name string) *Rulesfile {
for _, rf := range r.Rulesfiles {
if rf.Reserved || rf.Archived {
continue
}
if rf.Name == name {
return &rf
}

View File

@ -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
}

View File

@ -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)
}

View File

@ -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 (

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
@ -100,22 +101,25 @@ func ociTagsToUpdate(newTag string, existingTags []string) []string {
return tagsToUpdate
}
var existingSemvers []semver.Version
var existingFinalSemvers []semver.Version
for _, tag := range existingTags {
if sv, err := semver.Parse(tag); err == nil {
existingSemvers = append(existingSemvers, sv)
// ignore prereleases
if len(sv.Pre) == 0 {
existingFinalSemvers = append(existingFinalSemvers, sv)
}
}
}
if isLatestSemverForMinor(newSemver, existingSemvers) {
if isLatestSemverForMinor(newSemver, existingFinalSemvers) {
tagsToUpdate = append(tagsToUpdate, fmt.Sprintf("%d.%d", newSemver.Major, newSemver.Minor))
}
if isLatestSemverForMajor(newSemver, existingSemvers) {
if isLatestSemverForMajor(newSemver, existingFinalSemvers) {
tagsToUpdate = append(tagsToUpdate, fmt.Sprintf("%d", newSemver.Major))
}
if isLatestSemver(newSemver, existingSemvers) {
if isLatestSemver(newSemver, existingFinalSemvers) {
tagsToUpdate = append(tagsToUpdate, "latest")
}

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.
@ -71,6 +72,8 @@ func Test_ociTagsToUpdate(t *testing.T) {
{"latest_in_line", "0.1.3", []string{"0.1.2", "0.2.0", "0.3.1"}, []string{"0.1.3", "0.1"}},
{"version_1", "1.0.2", []string{"0.1.2", "0.2.0", "1.0.0", "2.0.0", "2.0.2"}, []string{"1", "1.0", "1.0.2"}},
{"prerelease", "0.1.4-rc1", []string{"0.1.2", "0.1.3"}, []string{"0.1.4-rc1"}},
{"latest_with_prerelease", "1.0.2", []string{"1.0.0", "1.0.1", "2.0.0-rc1"}, []string{"1", "1.0", "1.0.2", "latest"}},
{"not_latest_with_prerelease", "1.0.2", []string{"1.0.0", "1.0.1", "2.0.0-rc1", "2.0.0"}, []string{"1", "1.0", "1.0.2"}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: Apache-2.0
/*
Copyright (C) 2023 The Falco Authors.

View File

@ -47,3 +47,7 @@
name: The Falco Authors
sources:
- 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/

View File

@ -47,3 +47,7 @@
name: The Falco Authors
sources:
- 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/

View File

@ -8,7 +8,13 @@ rulesfiles:
email: cncf-falco-dev@lists.cncf.io
path: rules/falco_rules.yaml
license: apache-2.0
keywords:
- falco
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: applications
description: Application rules
authors: The Falco Authors
@ -19,3 +25,7 @@ rulesfiles:
path: rules/application_rules.yaml
url: https://github.com/falcosecurity/rules/blob/main/rules/application_rules.yaml
license: apache-2.0
signature:
cosign:
certificate-oidc-issuer: https://token.actions.githubusercontent.com
certificate-identity-regexp: https://github.com/falcosecurity/rules/

View File

@ -0,0 +1 @@
- required_engine_version: test

View File

@ -0,0 +1 @@
- required_engine_version: 15

View File

@ -0,0 +1 @@
- required_engine_version: 0.31.0

BIN
docs/images/announce.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
docs/images/arrow.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

BIN
docs/images/cross.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
docs/images/insight.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
docs/images/setting.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
docs/images/start.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

6
mkdocs.yml Normal file
View File

@ -0,0 +1,6 @@
site_name: Falcosecurity Rules
site_url: https://github.com/falcosecurity/rules
nav:
- Home: index.md
theme: material

View File

@ -0,0 +1,245 @@
# Falco Rules Adoption, Management and Maturity Framework
## Objective
The objective is to outline key enhancements and improvements to Falco, focusing on optimizing its rule adoption, customization, and management capabilities. The proposal also introduces a rules maturity framework to provide a structured approach for assessing and categorizing rules.
In more detail, this proposal aims to address the expectations of adopters by providing clear guidelines for rule contribution, including processes and criteria. It also aims to provide guidance on rule customization and tuning to help adopters optimize the detection capabilities of Falco for their specific environments. Lastly, the proposal aims to empower adopters by providing them with the necessary knowledge and resources to effectively manage and customize rules.
The proposed timeline for the initial completion of each item is the Falco 0.36 release, with further improvements being continuously added based on feedback.
## Current State
This section highlights the current (as of June 6, 2023) procedures and resources for rules creation and adoption and serves as an assessment:
- The Falco Project website provides detailed explanations on how to [write](https://falco.org/docs/rules/) Falco rules along with references such as the [supported fields](https://falco.org/docs/reference/rules/supported-fields/) for conditions and outputs.
- Community members contribute rules via opening a PR against the [falcosecurity/rules](https://github.com/falcosecurity/rules) repo.
- [Tutorials](https://falco.org/docs/tutorials/) and [blog posts](https://falco.org/tags/rules/) related to rules are available on the Falco website, along with numerous references to webinars and conference talks.
- Falco features a CLI tool called [falcoctl](https://github.com/falcosecurity/falcoctl) to manage the lifecycle of rules (installation, updates), see [blog post](https://falco.org/blog/falcoctl-install-manage-rules-plugins/).
- The rules framework of Falco is battle-tested and proven to be reliable in production environments. It is used by a diverse range of [organizations](https://github.com/falcosecurity/falco/blob/master/ADOPTERS.md).
- Existing rules yaml files
- Main Falco rules ([falco_rules.yaml](https://github.com/falcosecurity/rules/blob/main/rules/falco_rules.yaml)) based on syscall and container events.
- [application_rules.yaml](https://github.com/falcosecurity/rules/blob/main/rules/application_rules.yaml) also contains rules based on network-related syscalls, which may seem misleading if you expect those rules to be present in the regular "falco_rules.yaml" file.
- Plugins rules are based on third-party data sources that Falco hooks into, in addition to or instead of kernel tracing, e.g. [k8s_audit_rules.yaml](https://github.com/falcosecurity/plugins/blob/master/plugins/k8saudit/rules/k8s_audit_rules.yaml), [github.yaml](https://github.com/falcosecurity/plugins/blob/master/plugins/github/rules/github.yaml), [okta_rules.yaml](https://github.com/falcosecurity/plugins/blob/master/plugins/okta/rules/okta_rules.yaml) or [aws_cloudtrail_rules.yaml](https://github.com/falcosecurity/plugins/blob/master/plugins/cloudtrail/rules/aws_cloudtrail_rules.yaml).
- Rules include a concise description and a sense of `priority` to determine the level at which they should be loaded and activated. Furthermore, there is a key called `tag` that includes additional filter fields and information. This information may indicate whether a rule is designed to detect abnormal behavior in workloads running on the host or in containers. The tag field may also include details about the corresponding Mitre Attack phase and [TTP](https://attack.mitre.org/tactics/enterprise/) (Tactics, Techniques, and Procedures) codes.
- Falco provides an [overview](https://github.com/falcosecurity/rules/blob/main/rules_inventory/rules_overview.md) document that summarizes rules related to syscalls and container events and an experimental interactive [rules explorer website](https://github.com/Issif/falco-rules-explorer).
- Falco's website features [FAQ](https://falco.org/about/faq/) and [About](https://falco.org/about/) pages providing detailed technical information.
## Proposed Improvements
### Highlight and Outline Primary Use Cases
Adopters will be presented with clear primary use cases to better understand how Falco can be leveraged. These use cases will encompass "Threat Detection" and "Compliance". Rules specifically related to compliance will be tagged accordingly, based on their use case, similar to how we tag rules with the Mitre Attack phase.
> Falco serves two main use cases:
> - Threat Detection: Rule violations as indicators of compromise.
> - Compliance: Detecting unauthorized changes to files under PCI/DSS.
### Rules Maturity Framework
A rules maturity framework will be developed for Falco users to better facilitate the adoption of non-custom rules. This framework ensures a smooth transition for adopters, whether they use rules generically or for specific use cases. A smooth adoption process is defined by making it easy for adopters to understand each rule and also gain an understanding of not just what the rule is doing, but also how beneficial it can be under various circumstances. Additionally, adopters should have a clear idea of which rules can likely be adopted as-is versus which rules may require engineering efforts to evaluate and adopt. The rules maturity framework shall be accompanied by a guide that provides clear and unambiguous criteria for categorizing a rule that both the reviewer and contributor should adhere to.
The rules maturity framework will align 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. More details about this will be explained in the respective maturity level section.
Levels (new Falco tags):
- **maturity_stable** (enabled by default) indicates that the rule has undergone thorough evaluation by experts with hands-on production experience. These experts have determined that the rules embody best practices and exhibit optimal robustness, making it more difficult for attackers to bypass Falco. These rules are highly relevant for addressing broader threats and are recommended for customization to specific environments if necessary. They primarily focus on universal system-level detections, such as generic reverse shells or container escapes, which establish a solid baseline for threat detection across diverse industries. This inherent bias against including more application-specific detections is due to their potential lack of broad relevance or applicability. However, to mitigate this bias, a grey area will be reserved, enabling case-by-case judgments to be made.
- **maturity_incubating** (disabled by default) indicates that the rules address relevant threats, provide a certain level of robustness guarantee, and adhere to best practices in rule writing. Furthermore, it signifies that the rules have been identified by experts as catering to more specific use cases, which may or may not be relevant for each adopter. This category is expected to include a larger number of application-specific rules.
- **maturity_sandbox** (disabled by default) 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** (disabled by default), 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.
> Falco introduces new additional tags, that is:
>
> `maturity_stable`
> `maturity_incubating`
> `maturity_sandbox`
> `maturity_deprecated`
>
> for each rule. This 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. As a minimum requirement, each rule must go through the `maturity_incubating` state before advancing to `maturity_stable`. Only `maturity_stable` rules will be enabled by default. We use the existing tags mechanisms to build upon a battle-proven solution and will provide transparent configurability through the `falco.yaml` file to support the unique use cases of adopters.
>
> Furthermore, we will start by implementing tagging for the rules and establishing new guides. Subsequently, we will gather feedback from the community. In the future, we believe it would be beneficial to divide the rules files into separate entities: `falco_rules.yaml` (keeping the old established file name for the stable rules), `falco-incubating_rules.yaml`, `falco-sandbox_rules.yaml`, and `falco-deprecated_rules.yaml`. However, since this change could potentially disrupt some adopters and result in breaking changes to the order in which rules are loaded, we believe it is necessary to prioritize other improvements first. For instance, we may need to introduce features such as allowing multiple rules to match on a single event or providing the ability to customize the loading order, to name just a few.
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.
As users become more familiar with Falco and better understand their unique environments, they can gradually fine-tune the default 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 crucial to convey to adopters, as it is important to keep in mind that 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 consistently, they can add a next set of rules. This set may include rules with `maturity_incubating`, providing more specific detections. These efforts will be supported by guidance on rule customization and broader educational initiatives that focus on Linux OS runtime security.
> Experts in the field, with expertise in areas such as offensive security, Linux kernel tracing, production deployment, cyber security, threat detection, compliance, data analysis, and data science, will be responsible for assessing the maturity levels of rules. These experts have a deep familiarity with Falco.
*Disclaimer*: The Falco maintainers understand that this approach may not be perfect from the beginning and that it requires field experience and community feedback to move towards a desired end solution. We have chosen the outlined rules maturity tagging approach as an initial solution to introduce more clarity and flexibility than we currently have while still aiming to keep things relatively simple in the beginning.
### Define Rule Contribution Process
A guide will be established to facilitate the contribution of new rules or updates to existing ones. This guide will serve as an extension to the generic Falco [contributing guide](https://github.com/falcosecurity/.github/blob/main/CONTRIBUTING.md). This guide will outline clear acceptance criteria for each maturity level and establish minimum requirements for rule creation. These criteria will be utilized to assess the acceptance or rejection of a rule.
This guide will also include information on how the community is intended to share rules. As a general principle, the project's main objective is to curate an optimal set of "stable" rules that are included in the main [falco_rules.yaml](https://github.com/falcosecurity/rules/blob/main/rules/falco_rules.yaml) file and also published as OCI artifacts. However, there may be opportunities to create additional platforms for ad-hoc rules sharing that do not necessarily need to meet the strict criteria set by the Falco maintainers.
The minimum criteria for rules creation shall include:
*Correctness*
The criteria with regard to correctness shall include, at a minimum:
- 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 (read more under the testing section).
*Robustness*
To enhance the effectiveness of detection, priority is given to behavioral detections, as opposed to simple 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 at a particular point in time or attack scenario. For concrete examples of more robust rules, please refer to Appendix 1.
*Relevance*
Determining relevance is often the most subjective criterion, as it requires expertise in offensive security, cyber defense, and real-world production settings for accurate assessment. Questions such as whether these threats are a priority for most organizations or if we can provide enough context for a security analyst to appropriately act on the alerts as part of their incident response workflows are top of mind when assessing the overall relevance. Relevance is a key factor that indirectly reflects both robustness and significance, but more importantly, it indicates whether a particular security threat is significant to most adopters and, consequently, beneficial to detect.
Possible criteria:
- Cover relevant attack vectors across various industries.
- Emphasize profiling over signatures.
- Effectiveness of the rule across diverse workloads.
- Guidance and templates are provided to assist with tuning.
*Testing*
How was the rule tested? The desired testing approach includes not only functional end-to-end tests in virtual machines (VMs), but also deployments in real-world infrastructure. The Falco maintainers will provide guidance and support to contributors throughout the testing process, recognizing that it will vary significantly for each rule due to its unique nature. Additionally, while we aim to automate tests and expand test coverage, we acknowledge that it is a large engineering effort that will take time. Therefore, manual tests during the review processes and best effort deployment tests will be necessary in the interim.
### Guidance on Rule Customization and Tuning
Each rule tagged as "Stable" will provide clear guidance on how it can be tuned, customized, or combined with other rules if applicable. Over time, a catalog of general best tuning practices will be developed. For specific examples, please refer to Appendix 2.
### Setting Expectations for Adopters
Setting clear expectations for adopters of Falco is crucial. While Falco is a powerful security monitoring tool, it's important to be aware of its limitations and maintain realistic expectations. Please refer to Appendix 3 for specific examples of current limitations of Falco.
Adopters should understand the importance of consulting the latest [documentation](https://falco.org/) and updates to ensure they have accurate and up-to-date information. Additionally, the project [roadmap](https://github.com/orgs/falcosecurity/projects/5) offers valuable insights into features that are currently being developed or planned for future releases. Keeping informed about the roadmap helps adopters understand the direction of Falco's development and the potential enhancements that may be available in the future for writing more powerful detections.
In addition, effectively utilizing Falco requires expertise in various domains, including offensive security, Linux kernel tracing, production deployment, cyber security, threat detection, compliance, data analysis, and data science. Depending on the specific domain it may be easier to get started or require a little ramping up.
## Key Results for Falco 0.36
In summary, the following action items are planned to be completed leading up to the Falco 0.36 release:
- Clearly communicate Falco's primary uses: threat detection and compliance.
- Establish specific criteria for each rules maturity level and define general criteria for creating, contributing, and updating rules based on their respective maturity levels.
- Create a clear PR template for the rules repo that references the criteria for rules acceptance.
- Offer guidance and templates for rules tuning purposes.
- Audit each existing rule and assign a maturity level to it. Ensure a minimum set of 20 or more diverse rules are identified as "stable" and enabled by default. These rules should cover a wide range of top cyber threats and have the potential to effectively detect indicators of compromise related to those threats.
- Audit the existing rules from a compliance perspective and tag them with the compliance related tag if applicable. By the release of Falco 0.36, ensure that there are at least three template Falco rules in the "incubating" state specifically designed for "compliance" use cases.
- Add support for the new maturity tags in the Falco binary and configuration file.
- Update Falco's website to concisely document new processes and information, making it a single source of truth for creating, tuning, or contributing rules.
As a result of these changes, Falco's principles for rules adoption, maturity, and management will be updated. However, adopters can continue to use Falco as they have been doing before.
*Disclaimer*: If new information becomes available during the implementation of these changes, such as expanded feedback from the community, the Falco maintainers reserve the right to be flexible and adaptive, and re-evaluate choices and designs.
## Appendix
### Appendix 1
Here are some examples of more robust rules with a brief description of why they are considered more robust and behavioral-based rather than relying too heavily on signatures:
<details>
<summary>Detect release_agent File Container Escapes</summary>
<p>
Detecting attempts to escape a container is a crucial detection for modern container orchestration systems like Kubernetes. This rule stands out due to its inclusion of preconditions, which verify the necessary privileges of the container. Without these preconditions, the specific TTPs associated with container escape are not feasible.
</p>
<p>
The rule is based on the open syscall while monitoring file writing activities, specifically looking for a string match on the file name "release_agent". This approach is robust because Linux expects the cgroup's release_agent file to be named in this manner.
</p>
<p>
One downside of the rule is that it addresses only one specific TTP. Enabling additional rules like "Change thread namespace" can enhance coverage for other container escape methods.
</p>
</details>
<details>
<summary>Drop and execute new binary in container</summary>
<p>
The Falco 0.34 release <a href="https://falco.org/blog/falco-0-34-0/#even-more-ways-of-catching-suspicious-executions"> note</a> provides a concise summary of how high-value kernel signals can greatly simplify the task of detecting suspicious executions that occur when a malicious implant is dropped and executed. Instead of relying on complex checks for executable paths, the focus shifts to identifying executables that were not part of the container image and were executed from the container's upper overlayfs layer shortly after being dropped.
</p>
<p>
This approach narrows detection scope, increases tractability, and eliminates the need for inspecting unfamiliar or unusual executable paths. By leveraging high-value kernel signals, detections become more precise, removing ambiguity and providing crucial context.
</p>
</details>
</br>
### Appendix 2
Tuning Falco rules can vary in complexity and involve tradeoffs based on the environment. While some tuning processes are straightforward, there are cases that require nuanced adjustments. It's essential for adopters to be aware that on-host rule tuning may have limitations.
In some scenarios, adopters may benefit from acknowledging that operationalizing detections could require additional data analysis and correlation. This implies that adopting organizations may need to leverage data lake systems for further analysis and contextual correlation of the generated alerts, going beyond rule tuning.
Here are some general tricks for tuning on-host rules:
<details>
<summary>Profiling</summary>
<p>
Profiling the environment can be effective in detecting abnormal behaviors that may be considered normal in system-critical applications but outliers in standard applications. Implementing a simple allow list, such as for container names or namespaces, can already provide valuable assistance. This approach also aligns with the practice of clearly defining the crown jewel applications for which robust detections are desired.
</p>
</details>
<details>
<summary>Linux concepts / behavioral indicators</summary>
<p>
Another aspect of tuning a detection involves considering behavioral aspects related to Linux concepts. For example, a detection can be tuned based on the presence of a shell or a Java process in the parent process lineage, or detecting file manipulations while maintaining manual interactive shell access to a container. By incorporating these behavioral indicators, the detection can become more specific, relevant, and effective in identifying potential security threats.
</p>
</details>
</br>
### Appendix 3
Examples of existing gaps in Falco for threat detection, as of June 6, 2023, include:
<details>
<summary>Deep kernel-level monitoring</summary>
<p>
Falco operates at the kernel level but does not provide deep visibility into all aspects of kernel internals. It focuses on monitoring system calls and other observable events but may not capture low-level kernel activities.
</p>
</details>
<details>
<summary>Network packet inspection</summary>
<p>
Falco's primary focus is on monitoring system calls, and while it can detect network-related system calls, it may not offer extensive network packet inspection capabilities. Additionally, when considering modern cloud architectures with load balancers in front of application backend servers, there are inherent limitations in L3/4 network monitoring. Lastly, keeping in mind that Falco runs on each host in isolation, it means that certain correlations and detailed network introspection are still being extended and improved upon.
</p>
</details>
<details>
<summary>Full-stack application monitoring</summary>
<p>
Essentially, Falco is designed to monitor the Linux kernel and system-level activities. While it can capture certain application-related events, it may not provide comprehensive monitoring and visibility into the full application stack. However, there are exceptions where Falco has expanded its monitoring coverage to additional data sources using the <a href="https://falco.org/docs/plugins/"> plugins</a> framework. One notable example is the integration with Kubernetes audit logs, which provides monitoring at the control plane level within a Kubernetes infrastructure. In addition, Falco's underlying libraries possess the capability to capture abnormal behavior at higher levels of the stack, such as analyzing HTTP requests. However, this potential is currently not exposed in Falco.
</p>
</details>
<details>
<summary>Advanced behavior analysis / anomaly detection</summary>
<p>
Falco excels at detecting known patterns and rules-based anomalies. However, it currently may have limitations when it comes to advanced behavior analysis, on host anomaly detection, or identifying zero-day exploits that do not exhibit known patterns.
</p>
</details>
</br>
Consult the project [roadmap](https://github.com/orgs/falcosecurity/projects/5) and official [documentation](https://falco.org/) for up to date information on Falco's current capabilities.

View File

@ -1,3 +1,4 @@
# SPDX-License-Identifier: Apache-2.0
#
# Copyright (C) 2023 The Falco Authors.
#
@ -15,7 +16,6 @@
# limitations under the License.
#
rulesfiles:
- name: falco-rules
description: Falco rules that are loaded by default
@ -27,13 +27,56 @@ rulesfiles:
path: rules/falco_rules.yaml
license: apache-2.0
url: https://github.com/falcosecurity/rules/blob/main/rules/falco_rules.yaml
- name: application-rules
description: Application rules
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
contact: https://falco.org/community
maintainers:
- name: The Falco Authors
email: cncf-falco-dev@lists.cncf.io
path: rules/application_rules.yaml
url: https://github.com/falcosecurity/rules/blob/main/rules/application_rules.yaml
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
contact: https://falco.org/community
maintainers:
- name: The Falco Authors
email: cncf-falco-dev@lists.cncf.io
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
contact: https://falco.org/community
maintainers:
- name: The Falco Authors
email: cncf-falco-dev@lists.cncf.io
path: rules/falco-deprecated_rules.yaml
license: apache-2.0
url: https://github.com/falcosecurity/rules/blob/main/rules/falco-deprecated_rules.yaml
- name: application-rules
archived: true
description: This rules files has been archived and is no longer maintained
authors: The Falco Authors
contact: https://falco.org/community
maintainers:
- name: The Falco Authors
email: cncf-falco-dev@lists.cncf.io
path: archive/application_rules.yaml
url: https://github.com/falcosecurity/rules/blob/main/archive/application_rules.yaml
license: apache-2.0

3
rules/OWNERS Normal file
View File

@ -0,0 +1,3 @@
approvers:
- darryk10
- loresuso

View File

@ -0,0 +1,195 @@
# SPDX-License-Identifier: Apache-2.0
#
# Copyright (C) 2025 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.
#
# Information about rules tags and fields can be found here: https://falco.org/docs/rules/#tags-for-current-falco-ruleset
# The initial item in the `tags` fields reflects the maturity level of the rules introduced upon the proposal https://github.com/falcosecurity/rules/blob/main/proposals/20230605-rules-adoption-management-maturity-framework.md
# `tags` fields also include information about the type of workload inspection (host and/or container), and Mitre Attack killchain phases and Mitre TTP code(s)
# Mitre Attack References:
# [1] https://attack.mitre.org/tactics/enterprise/
# [2] https://raw.githubusercontent.com/mitre/cti/master/enterprise-attack/enterprise-attack.json
# Starting with version 8, the Falco engine supports exceptions.
# However the Falco rules file does not use them by default.
- 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
# condition: (never_true)
# can be used in a rules' expression with double negation `and not allowed_ssh_hosts` which effectively evaluates
# to true and does nothing, the perfect empty template for `logical` cases as opposed to list templates.
# When tuning the rule you can override the macro with something useful, e.g.
# - macro: allowed_ssh_hosts
# condition: (evt.hostname contains xyz)
- macro: never_true
condition: (evt.num=0)
# RFC1918 addresses were assigned for private network usage
- list: rfc_1918_addresses
items: ['"10.0.0.0/8"', '"172.16.0.0/12"', '"192.168.0.0/16"']
- macro: outbound
condition: >
(((evt.type = connect and evt.dir=<) or
(evt.type in (sendto,sendmsg) and evt.dir=< and
fd.l4proto != tcp and fd.connected=false and fd.name_changed=true)) and
(fd.typechar = 4 or fd.typechar = 6) and
(fd.ip != "0.0.0.0" and fd.net != "127.0.0.0/8" and not fd.snet in (rfc_1918_addresses)) and
(evt.rawres >= 0 or evt.res = EINPROGRESS))
# Very similar to inbound/outbound, but combines the tests together
# for efficiency.
- macro: inbound_outbound
condition: >
((((evt.type in (accept,accept4,listen,connect) and evt.dir=<)) and
(fd.typechar = 4 or fd.typechar = 6)) and
(fd.ip != "0.0.0.0" and fd.net != "127.0.0.0/8") and
(evt.rawres >= 0 or evt.res = EINPROGRESS))
- macro: ssh_port
condition: (fd.sport=22)
# In a local/user rules file, you could override this macro to
# enumerate the servers for which ssh connections are allowed. For
# example, you might have a ssh gateway host for which ssh connections
# are allowed.
#
# In the main falco rules file, there isn't any way to know the
# specific hosts for which ssh access is allowed, so this macro just
# repeats ssh_port, which effectively allows ssh from all hosts. In
# the overridden macro, the condition would look something like
# "fd.sip="a.b.c.d" or fd.sip="e.f.g.h" or ..."
- macro: allowed_ssh_hosts
condition: (never_true)
- rule: Disallowed SSH Connection
desc: >
Detect any new SSH connection on port 22 to a host other than those in an allowed list of hosts.
This rule absolutely requires profiling your environment beforehand. Network-based rules are extremely
crucial in any security program, as they can often provide the only definitive evidence. However,
effectively operationalizing them can be challenging due to the potential for noise.
condition: >
inbound_outbound
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
priority: NOTICE
tags: [maturity_deprecated, host, container, network, mitre_lateral_movement, T1021.004]
# These rules and supporting macros are more of an example for how to
# use the fd.*ip and fd.*ip.name fields to match connection
# information against ips, netmasks, and complete domain names.
#
# To use this rule, you should enable it and
# populate allowed_{source,destination}_{ipaddrs,networks,domains} with the
# values that make sense for your environment.
# Note that this can be either individual IPs or netmasks
- list: allowed_outbound_destination_ipaddrs
items: ['"127.0.0.1"', '"8.8.8.8"']
- list: allowed_outbound_destination_networks
items: ['"127.0.0.1/8"']
- list: allowed_outbound_destination_domains
items: [google.com, www.yahoo.com]
- rule: Unexpected outbound connection destination
desc: >
Detect any outbound connection to a destination outside of an allowed set of ips, networks, or domain names.
This rule absolutely requires profiling your environment beforehand. Network-based rules are extremely crucial
in any security program, as they can often provide the only definitive evidence. However, effectively operationalizing
them can be challenging due to the potential for noise.
condition: >
outbound
and not ((fd.sip in (allowed_outbound_destination_ipaddrs)) or
(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
priority: NOTICE
tags: [maturity_deprecated, host, container, network, mitre_command_and_control, TA0011]
# Use this to test whether the event occurred within a container.
- macro: container
condition: (container.id != host)
- list: allowed_image
items: [] # add image to monitor, i.e.: bitnami/nginx
- list: authorized_server_binary
items: [] # add binary to allow, i.e.: nginx
- list: authorized_server_port
items: [] # add port to allow, i.e.: 80
# # How to test:
# kubectl run --image=nginx nginx-app --port=80 --env="DOMAIN=cluster"
# kubectl expose deployment nginx-app --port=80 --name=nginx-http --type=LoadBalancer
# # On minikube:
# minikube service nginx-http
# # On general K8s:
# kubectl get services
# kubectl cluster-info
# # Visit the Nginx service and port, should not fire.
# # Change rule to different port, then different process name, and test again that it fires.
- rule: Outbound or Inbound Traffic not to Authorized Server Process and Port
desc: >
Detect traffic to an unauthorized server process and port within pre-defined containers.
This rule absolutely requires profiling your environment beforehand and also necessitates adjusting the list of containers
to which this rule will be applied. The current expression logic will never evaluate to true unless the list is populated.
Network-based rules are extremely crucial in any security program, as they can often provide the only definitive evidence.
However, effectively operationalizing them can be challenging due to the potential for noise. Notably, this rule is challenging
to operationalize.
condition: >
inbound_outbound
and container
and container.image.repository in (allowed_image)
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
priority: WARNING
tags: [maturity_deprecated, container, network, mitre_discovery, TA0011, NIST_800-53_CM-7]
- list: c2_server_ip_list
items: []
- list: c2_server_fqdn_list
items: []
- rule: Outbound Connection to C2 Servers
desc: >
Detect outbound connections to command and control servers using a list of IP addresses and fully qualified domain names (FQDNs).
This rule absolutely requires profiling your environment beforehand and also necessitates adjusting the template lists. The current
expression logic will never evaluate to true unless the lists are populated. Network-based rules are extremely crucial in any
security program, as they can often provide the only definitive evidence. However, effectively operationalizing them can be challenging
due to the potential for noise. Notably, this rule is challenging to operationalize.
condition: >
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
priority: WARNING
enabled: false
tags: [maturity_deprecated, host, container, network, mitre_command_and_control, TA0011]

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More