Skip to content

Commit 9eac5b9

Browse files
authored
Implement IEP009 - product & vuln. identification (#2574)
* Implement IEP009 - product & vuln. identification The related IEP has already been discussed and open for more than a year. * Fix order * Upgrade harmonisation * Add tests * Renumbering to 3.4.2 release * Fix style issue
1 parent b907411 commit 9eac5b9

File tree

6 files changed

+86
-0
lines changed

6 files changed

+86
-0
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,18 @@ Please refer to the [NEWS](NEWS.md) for a list of changes which have an affect o
2727

2828
### Data Format
2929

30+
- Implementing [IEP009](https://github.com/certtools/ieps/tree/main/009) introducing fields to
31+
identify products and vulnerabilities: `product.full_name`, `product.name`, `product.vendor`,
32+
`product.version`, `product.vulnerabilities`. To store in existing PostgreSQL instances, a following
33+
schema update will be necessary:
34+
```sql
35+
ALTER TABLE events ADD "product.full_name" text;
36+
ALTER TABLE events ADD "product.name" text;
37+
ALTER TABLE events ADD "product.vendor" text;
38+
ALTER TABLE events ADD "product.version" text;
39+
ALTER TABLE events ADD "product.vulnerabilities" text;
40+
```
41+
3042
### Bots
3143
#### Collectors
3244
- `intelmq.bots.collectors.mail.collector_mail_attach`: Decrypt GPG attachments (PR#2623 by Edvard Rejthar).

NEWS.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,15 @@ Python `>=3.9` is now required, which is available on all platforms supported by
1919
### Tools
2020

2121
### Data Format
22+
To save new fields from IntelMQ Data Format in existing PostgreSQL instances, the following schema
23+
update is necessary:
24+
```sql
25+
ALTER TABLE events ADD "product.full_name" text;
26+
ALTER TABLE events ADD "product.name" text;
27+
ALTER TABLE events ADD "product.vendor" text;
28+
ALTER TABLE events ADD "product.version" text;
29+
ALTER TABLE events ADD "product.vulnerabilities" text;
30+
```
2231

2332
### Configuration
2433

intelmq/etc/harmonization.conf

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,26 @@
209209
"description": "Event data converted into foreign format, intended to be exported by output plugin.",
210210
"type": "JSON"
211211
},
212+
"product.full_name": {
213+
"description": "A human readable product name. If a machine-readable format isn't available, this field should be used. It can directly use the version identification strings presented by the product. If not given, a good enough value can usually be constructed by concatenating product.product and product.version, or by consulting external sources such as the CPE Product Dictionary. Example: openssh_/8.9",
214+
"type": "String"
215+
},
216+
"product.name": {
217+
"description": "Product name, recommended being as the product in the CPE format. Example: openssh",
218+
"type": "LowercaseString"
219+
},
220+
"product.vendor": {
221+
"description": "Vendor name, recommended being as vendor in the CPE format. Example: openbsd",
222+
"type": "LowercaseString"
223+
},
224+
"product.version": {
225+
"description": "Product version, recommended being as version in the CPE format. Example: 8.9",
226+
"type": "LowercaseString"
227+
},
228+
"product.vulnerabilities": {
229+
"description": "List of vulnerability IDs, separated by semicolons. It's recommended to use a CVE ID where available, and other easily retrievable IDs in other cases, e.g. Github Advisory Database ID. Each vulnerability should only be listed once, and multiple values should be used if there are several different vulnerabilities. However, it's not necessary for a source to list all possible vulnerabilities for a given piece of software. Example: cve-2023-38408;cve-2023-28531;cve-2008-3844;cve-2007-2768",
230+
"type": "LowercaseString"
231+
},
212232
"protocol.application": {
213233
"description": "e.g. vnc, ssh, sip, irc, http or smtp.",
214234
"length": 100,

intelmq/lib/upgrades.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
'v322_removed_feeds_and_bots',
4444
'v340_deprecations',
4545
'v341_blueliv_removal',
46+
'v342_new_fields'
4647
]
4748

4849

@@ -998,6 +999,33 @@ def v341_blueliv_removal(configuration, harmonization, dry_run, **kwargs):
998999
return message, configuration, harmonization
9991000

10001001

1002+
def v342_new_fields(configuration, harmonization, dry_run, **kwargs):
1003+
"""
1004+
Add new fields to IntelMQ Data Format
1005+
"""
1006+
changed = None
1007+
if "event" not in harmonization:
1008+
return changed, configuration, harmonization
1009+
1010+
builtin_harmonisation = load_configuration(
1011+
resource_filename("intelmq", "etc/harmonization.conf")
1012+
)
1013+
for field in [
1014+
"product.full_name",
1015+
"product.name",
1016+
"product.vendor",
1017+
"product.version",
1018+
"product.vulnerabilities",
1019+
]:
1020+
if field not in harmonization["event"]:
1021+
if field not in builtin_harmonisation["event"]:
1022+
# ensure forward-compatibility if we ever remove something from harmonisation
1023+
continue
1024+
harmonization["event"][field] = builtin_harmonisation["event"][field]
1025+
changed = True
1026+
return changed, configuration, harmonization
1027+
1028+
10011029
UPGRADES = OrderedDict([
10021030
((1, 0, 0, 'dev7'), (v100_dev7_modify_syntax,)),
10031031
((1, 1, 0), (v110_shadowserver_feednames, v110_deprecations)),
@@ -1029,6 +1057,7 @@ def v341_blueliv_removal(configuration, harmonization, dry_run, **kwargs):
10291057
((3, 3, 1), ()),
10301058
((3, 4, 0), (v340_deprecations, )),
10311059
((3, 4, 1), (v341_blueliv_removal, )),
1060+
((3, 4, 2), (v342_new_fields, )),
10321061
])
10331062

10341063
ALWAYS = (harmonization,)

intelmq/tests/bin/initdb.sql

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ CREATE TABLE events (
4747
"misp.attribute_uuid" varchar(36),
4848
"misp.event_uuid" varchar(36),
4949
"output" jsonb,
50+
"product.full_name" text,
51+
"product.name" text,
52+
"product.vendor" text,
53+
"product.version" text,
54+
"product.vulnerabilities" text,
5055
"protocol.application" varchar(100),
5156
"protocol.transport" varchar(11),
5257
"raw" text,

intelmq/tests/lib/test_upgrades.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -872,6 +872,17 @@ def test_v341_blueliv_removal(self):
872872
self.assertIn('blueliv-parser', result[0])
873873
self.assertEqual(V341_BLUELIV_REMOVAL, result[1])
874874

875+
def test_v342_new_fields(self):
876+
""" Test adding new harmonisation fields """
877+
result = upgrades.v342_new_fields({}, {"event": {"old-field": "must stay"}}, False)
878+
self.assertTrue(result[0])
879+
self.assertIn("old-field", result[2]["event"])
880+
self.assertIn("product.full_name", result[2]["event"])
881+
self.assertIn("product.name", result[2]["event"])
882+
self.assertIn("product.vendor", result[2]["event"])
883+
self.assertIn("product.version", result[2]["event"])
884+
self.assertIn("product.vulnerabilities", result[2]["event"])
885+
875886
for name in upgrades.__all__:
876887
setattr(TestUpgradeLib, 'test_function_%s' % name,
877888
generate_function(getattr(upgrades, name)))

0 commit comments

Comments
 (0)