Skip to content

Commit

Permalink
fix conflict
Browse files Browse the repository at this point in the history
Signed-off-by: Stefano <[email protected]>
  • Loading branch information
darryk10 committed May 22, 2024
2 parents bf252ea + cd4faeb commit 3f2bff7
Show file tree
Hide file tree
Showing 100 changed files with 8,700 additions and 3,600 deletions.
1 change: 1 addition & 0 deletions .github/FALCO_VERSIONS
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
master
28 changes: 22 additions & 6 deletions .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -20,8 +22,6 @@
> /kind failing-test
> /kind feature

<!--
Please remove the leading whitespace before the `/kind <>` you uncommented.
Expand All @@ -43,14 +43,30 @@ 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**:

<!--
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 #
Expand Down
71 changes: 71 additions & 0 deletions .github/compare-rule-files.sh
Original file line number Diff line number Diff line change
@@ -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 changes: 12 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -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"
3 changes: 3 additions & 0 deletions .github/scripts/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
pandas==2.0.3
pyyaml===6.0.1
tabulate==0.9.0
160 changes: 160 additions & 0 deletions .github/scripts/rules_overview_generator.py
Original file line number Diff line number Diff line change
@@ -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))
54 changes: 54 additions & 0 deletions .github/workflows/create-comment.yaml
Original file line number Diff line number Diff line change
@@ -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/[email protected]
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/[email protected]
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')
});
Loading

0 comments on commit 3f2bff7

Please sign in to comment.