Skip to content

Commit 94b57c1

Browse files
committed
Merge branch 'collect-suricate_rules' into collect-sigma-rules-api
# Conflicts: # vulnerabilities/improvers/__init__.py
2 parents 30a01a9 + 3d424c0 commit 94b57c1

2 files changed

Lines changed: 118 additions & 0 deletions

File tree

vulnerabilities/improvers/__init__.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
from vulnerabilities.pipelines.v2_improvers import flag_ghost_packages as flag_ghost_packages_v2
3535
from vulnerabilities.pipelines.v2_improvers import relate_severities
3636
from vulnerabilities.pipelines.v2_improvers import sigma_rules
37+
from vulnerabilities.pipelines.v2_improvers import sigma_rules
38+
from vulnerabilities.pipelines.v2_improvers import suricata_rules
3739
from vulnerabilities.pipelines.v2_improvers import unfurl_version_range as unfurl_version_range_v2
3840
from vulnerabilities.pipelines.v2_improvers import yara_rules
3941
from vulnerabilities.utils import create_registry
@@ -114,5 +116,6 @@
114116
yara_rules.Dr4k0niaYaraRules,
115117
yara_rules.Umair9747YaraRules,
116118
clamav_rules.ClamVRulesImproverPipeline,
119+
suricata_rules.SuricataRulesImproverPipeline,
117120
]
118121
)
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
#
2+
# Copyright (c) nexB Inc. and others. All rights reserved.
3+
# VulnerableCode is a trademark of nexB Inc.
4+
# SPDX-License-Identifier: Apache-2.0
5+
# See http://www.apache.org/licenses/LICENSE-2.0 for the license text.
6+
# See https://github.com/aboutcode-org/vulnerablecode for support or download.
7+
# See https://aboutcode.org for more information about nexB OSS projects.
8+
#
9+
10+
from pathlib import Path
11+
12+
from aboutcode.pipeline import LoopProgress
13+
from fetchcode.vcs import fetch_via_vcs
14+
15+
from vulnerabilities.models import AdvisoryAlias
16+
from vulnerabilities.models import AdvisoryV2
17+
from vulnerabilities.models import DetectionRule
18+
from vulnerabilities.models import DetectionRuleTypes
19+
from vulnerabilities.pipelines import VulnerableCodePipeline
20+
from vulnerabilities.utils import find_all_cve
21+
from vulnerabilities.utils import get_advisory_url
22+
23+
24+
class SuricataRulesImproverPipeline(VulnerableCodePipeline):
25+
pipeline_id = "suricata-rules"
26+
27+
repo_pattern = [
28+
("https://github.com/sudohyak/suricata-rules", "**/*.rules"),
29+
("https://github.com/OISF/suricata", "rules/**/*.rules"),
30+
]
31+
32+
license_urls = """
33+
https://github.com/sudohyak/suricata-rules/blob/main/LICENSE
34+
35+
https://github.com/OISF/suricata?tab=GPL-2.0-2-ov-file
36+
https://github.com/OISF/suricata?tab=GPL-2.0-1-ov-file
37+
"""
38+
39+
@classmethod
40+
def steps(cls):
41+
return (
42+
cls.clone_repo,
43+
cls.collect_and_store_rules,
44+
cls.clean_downloads,
45+
)
46+
47+
def clone_repo(self):
48+
self.cloned_repos = []
49+
for repo_url, rglob_pattern in self.repo_pattern:
50+
self.log(f"Cloning `{repo_url}`")
51+
vcs_response = fetch_via_vcs(f"git+{repo_url}")
52+
self.cloned_repos.append(
53+
{"repo_url": repo_url, "rglob_pattern": rglob_pattern, "vcs_response": vcs_response}
54+
)
55+
56+
def collect_and_store_rules(self):
57+
"""
58+
Collect Suricata rules using rglob patterns and store/update
59+
them as DetectionRule objects.
60+
"""
61+
for cloned in self.cloned_repos:
62+
repo_url = cloned["repo_url"]
63+
rglob_pattern = cloned["rglob_pattern"]
64+
vcs_response = cloned["vcs_response"]
65+
66+
base_directory = Path(vcs_response.dest_dir)
67+
68+
rules_files = [p for p in base_directory.rglob(rglob_pattern) if p.is_file()]
69+
70+
rules_count = len(rules_files)
71+
self.log(f"Enhancing vulnerability data with {rules_count:,d} records from {repo_url}")
72+
progress = LoopProgress(total_iterations=rules_count, logger=self.log)
73+
74+
for file_path in progress.iter(rules_files):
75+
raw_text = file_path.read_text(encoding="utf-8")
76+
77+
source_url = get_advisory_url(
78+
file=file_path,
79+
base_path=base_directory,
80+
url=f"{repo_url}/blob/master/",
81+
)
82+
83+
cve_ids = find_all_cve(f"{file_path}\n{raw_text}")
84+
85+
advisories = set()
86+
for cve_id in cve_ids:
87+
alias = AdvisoryAlias.objects.filter(alias=cve_id).first()
88+
if alias:
89+
for adv in alias.advisories.all():
90+
advisories.add(adv)
91+
else:
92+
advs = AdvisoryV2.objects.filter(advisory_id=cve_id)
93+
for adv in advs:
94+
advisories.add(adv)
95+
96+
detection_rule, _ = DetectionRule.objects.update_or_create(
97+
source_url=source_url,
98+
rule_type=DetectionRuleTypes.SURICATA,
99+
defaults={
100+
"rule_text": raw_text,
101+
},
102+
)
103+
104+
for adv in advisories:
105+
detection_rule.related_advisories.add(adv)
106+
107+
def clean_downloads(self):
108+
for cloned in self.cloned_repos:
109+
vcs_response = cloned["vcs_response"]
110+
if vcs_response:
111+
self.log(f"Removing cloned repository: {vcs_response.dest_dir}")
112+
vcs_response.delete()
113+
114+
def on_failure(self):
115+
self.clean_downloads()

0 commit comments

Comments
 (0)