Skip to content

Commit d14611c

Browse files
authored
Merge pull request #2414 from zuo/jk/ssl-improvements-related-to-stomp-and-n6
STOMP+SSL-related changes: security fixes + convenience enhancement (+ doc updates/improvements)
2 parents 95e4fec + 0784db4 commit d14611c

File tree

10 files changed

+446
-109
lines changed

10 files changed

+446
-109
lines changed

CHANGELOG.md

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@
1919
if `auth_by_ssl_client_certificate` is *false*);
2020
- `password` (STOMP authentication passcode, default: "guest"; to be used only
2121
if `auth_by_ssl_client_certificate` is *false*).
22+
- Add the possibility to set the `ssl_ca_certificate` configuration parameter for
23+
`intelmq.bots.collectors.stomp.collector` and/or `intelmq.bots.outputs.stomp.output`
24+
to an empty string - which means that the SSL machinery used for STOMP communication
25+
will attempt to load the system’s default CA certificates (PR#2414 by Jan Kaliszewski).
2226

2327
### Core
2428
- `intelmq.lib.message`: For invalid message keys, add a hint on the failure to the exception: not allowed by configuration or not matching regular expression (PR#2398 by Sebastian Wagner).
@@ -27,7 +31,7 @@
2731
- `intelmq.lib.mixins`: Add a new class, `StompMixin` (defined in a new submodule: `stomp`),
2832
which provides certain common STOMP-bot-specific operations, factored out from
2933
`intelmq.bots.collectors.stomp.collector` and `intelmq.bots.outputs.stomp.output`
30-
(PR#2408 by Jan Kaliszewski).
34+
(PR#2408 and PR#2414 by Jan Kaliszewski).
3135

3236
### Development
3337
- Makefile: Add codespell and test commands (PR#2425 by Sebastian Wagner).
@@ -36,11 +40,16 @@
3640

3741
### Bots
3842
#### Collectors
39-
- `intelmq.bots.collectors.stomp.collector` (PR#2408 by Jan Kaliszewski):
40-
- Add support for authentication based on STOMP login and passcode,
41-
introducing 3 new configuration parameters (see above: *Configuration*).
43+
- `intelmq.bots.collectors.stomp.collector` (PR#2408 and PR#2414 by Jan Kaliszewski):
44+
- Drop support for versions of `stomp.py` older than `4.1.12`.
4245
- Update the code to support new versions of `stomp.py`, including the latest (`8.1.0`);
4346
fixes [#2342](https://github.com/certtools/intelmq/issues/2342).
47+
- Add support for authentication based on STOMP login and passcode, introducing three
48+
new configuration parameters (see above: *Configuration*).
49+
- Add support for loading the system’s default CA certificates, as an alternative to
50+
specifying the CA certificate(s) file path explicitly (see above: *Configuration*).
51+
- Fix (by carefully targeted monkey patching) certain security problems caused by
52+
SSL-related weaknesses that some versions of `stomp.py` suffer from.
4453
- Fix the reconnection behavior: do not attempt to reconnect after `shutdown`. Also,
4554
never attempt to reconnect if the version of `stomp.py` is older than `4.1.21` (it
4655
did not work properly anyway).
@@ -59,27 +68,35 @@
5968
file permissions on socket file, if it is in use.
6069

6170
#### Outputs
62-
- `intelmq.bots.outputs.stomp.output` (PR#2408 by Jan Kaliszewski):
63-
- Add support for authentication based on STOMP login and passcode,
64-
introducing 3 new configuration parameters (see above: *Configuration*).
71+
- `intelmq.bots.outputs.stomp.output` (PR#2408 and PR#2414 by Jan Kaliszewski):
72+
- Drop support for versions of `stomp.py` older than `4.1.12`.
6573
- Update the code to support new versions of `stomp.py`, including the latest (`8.1.0`).
74+
- Add support for authentication based on STOMP login and passcode, introducing three
75+
new configuration parameters (see above: *Configuration*).
76+
- Add support for loading the system’s default CA certificates, as an alternative to
77+
specifying the CA certificate(s) file path explicitly (see above: *Configuration*).
78+
- Fix (by carefully targeted monkey patching) certain security problems caused by
79+
SSL-related weaknesses that some versions of `stomp.py` suffer from.
6680
- Fix `AttributeError` caused by attempts to get unset attributes of `StompOutputBot`
6781
(`ssl_ca_cert` et consortes).
6882
- Add coercion of the `port` config parameter to `int`.
6983
- Add implementation of the `check` hook (verifying, in particular, accessibility
7084
of necessary file(s)).
71-
- Add `stomp.py` version check (raise `MissingDependencyError` if not `>=4.1.8`).
85+
- Add `stomp.py` version check (raise `MissingDependencyError` if not `>=4.1.12`).
7286
- Minor fixes/improvements and some refactoring (see also above: *Core*...).
7387

7488
### Documentation
7589
- Add a readthedocs configuration file to fix the build fail (PR#2403 by Sebastian Wagner).
7690
- Add a guide of developing extensions packages (PR#2413 by Kamil Mankowski)
7791
- Update/fix/improve the stuff related to the STOMP bots and integration with the *n6*'s
78-
Stream API (PR#2408 by Jan Kaliszewski).
92+
Stream API (PR#2408 and PR#2414 by Jan Kaliszewski).
7993
- Complete documentation overhaul. Change to markdown format. Uses the mkdocs-material (PR#2419 by Filip Pokorný).
8094

8195
### Packaging
8296
- Add `pendulum` to suggested packages, as it is required for the sieve bot (PR#2424 by Sebastian Wagner).
97+
- `debian/control`: in `Suggests` field, replace ``python3-stomp.py (>= 4.1.9)`` with
98+
``python3-stomp (>= 4.1.12)``, i.e., fix the package name by removing the `.py`
99+
suffix and bump the minimum version to `4.1.12` (PR#2414 by Jan Kaliszewski).
83100

84101
### Tests
85102

debian/control

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ Suggests: python3-geoip2 (>= 2.2.0),
5353
python3-pyasn (>= 1.5.0),
5454
python3-pymongo (>= 2.7.1),
5555
python3-sleekxmpp (>= 1.3.1),
56-
python3-stomp.py (>= 4.1.9),
56+
python3-stomp (>= 4.1.12),
5757
python3-pendulum
5858
Description: Solution for IT security teams for collecting and processing security feeds
5959
IntelMQ is a solution for IT security teams (CERTs, CSIRTs, abuse

docs/user/bots.md

Lines changed: 80 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1184,35 +1184,49 @@ Install the `stomp.py` library from PyPI:
11841184
pip3 install -r intelmq/bots/collectors/stomp/REQUIREMENTS.txt
11851185
```
11861186

1187+
Alternatively, you may want to install it using your OS's native
1188+
packaging tools, e.g.:
1189+
1190+
```bash
1191+
apt install python3-stomp
1192+
```
1193+
1194+
Apart from that, depending on what STOMP server you connect to, you may
1195+
need to obtain, from the organization or company owning the server, one
1196+
or more of the following security/authentication-related resources:
1197+
1198+
* CA certificate file;
1199+
* either: *client certificate* and *client certificate's key* files,
1200+
or: *username* (STOMP *login*) and *password* (STOMP *passcode*).
1201+
1202+
Also, you will need to know an appropriate STOMP *destination* (aka
1203+
*exchange point*), e.g. `/exchange/my.example.org/*.*.*.*`.
1204+
11871205
**Parameters (also expects [feed parameters](#feed-parameters)):**
11881206

11891207
**`server`**
11901208

1191-
(required, string) Hostname of the STOMP server.
1209+
(required, string) STOMP server's hostname or IP, e.g. "n6stream.cert.pl" (which is default)
11921210

11931211
**`port`**
11941212

1195-
(optional, integer) Defaults to 61614.
1213+
(optional, integer) STOMP server's port number (default: 61614)
11961214

11971215
**`exchange`**
11981216

1199-
(required, string) STOMP *destination* to subscribe to, e.g. "/exchange/my.org/*.*.*.*"
1217+
(required, string) STOMP *destination* to subscribe to, e.g. `"/exchange/my.org/*.*.*.*"`
12001218

1201-
**`username`**
1202-
1203-
(optional, string) Username to use.
1219+
**`heartbeat`**
12041220

1205-
**`password`**
1206-
1207-
(optional, string) Password to use.
1221+
(optional, integer) default: 6000
12081222

12091223
**`ssl_ca_certificate`**
12101224

1211-
(optional, string) Path to trusted CA certificate.
1225+
(optional, string) Path to CA file, or empty string to load system's default CA certificates
12121226

12131227
**`auth_by_ssl_client_certificate`**
12141228

1215-
(optional, boolean) Whether to authenticate using TLS certificate. (Set to false for new *n6* auth.) Defaults to true.
1229+
(optional, boolean) Default: true (note: false is needed for new *n6* auth)
12161230

12171231
**`ssl_client_certificate`**
12181232

@@ -1222,6 +1236,14 @@ pip3 install -r intelmq/bots/collectors/stomp/REQUIREMENTS.txt
12221236

12231237
(optional, string) Path to client private key to use for TLS connections.
12241238

1239+
**`username`**
1240+
1241+
(optional, string) Username to use.
1242+
1243+
**`password`**
1244+
1245+
(optional, string) Password to use.
1246+
12251247
---
12261248

12271249
### Twitter (REMOVE?) <div id="intelmq.bots.collectors.twitter.collector_twitter" />
@@ -5135,72 +5157,87 @@ This bot pushes data to any STOMP stream. STOMP stands for Streaming Text Orient
51355157
51365158
**Requirements**
51375159
5138-
Install the stomp.py library, e.g. [apt install python3-stomp.py] or [pip install stomp.py].
5160+
Install the `stomp.py` library from PyPI:
51395161
5140-
You need a CA certificate, client certificate and key file from the organization / server you are connecting to. Also
5141-
you will need a so called "exchange point".
5162+
```bash
5163+
pip3 install -r intelmq/bots/outputs/stomp/REQUIREMENTS.txt
5164+
```
51425165

5143-
**Parameters:**
5166+
Alternatively, you may want to install it using your OS's native
5167+
packaging tools, e.g.:
51445168

5145-
**`exchange`**
5169+
```bash
5170+
apt install python3-stomp
5171+
```
51465172

5147-
(optional, string) The exchange to push to. Defaults to `/exchange/_push`.
5173+
Apart from that, depending on what STOMP server you connect to, you may
5174+
need to obtain, from the organization or company owning the server, one
5175+
or more of the following security/authentication-related resources:
51485176

5149-
**`username`**
5177+
* CA certificate file;
5178+
* either: *client certificate* and *client certificate's key* files,
5179+
or: *username* (STOMP *login*) and *password* (STOMP *passcode*).
51505180

5151-
(optional, string) Username to use.
5181+
Also, you will need to know an appropriate STOMP *destination* (aka
5182+
*exchange point*), e.g. `/exchange/_push`.
51525183

5153-
**`password`**
5184+
**Parameters:**
51545185

5155-
(optional, string) Password to use.
5186+
**`server`**
51565187

5157-
**`ssl_ca_certificate`**
5188+
(optional, string) STOMP server's hostname or IP, e.g. "n6stream.cert.pl" or "127.0.0.1" (which is default)
51585189

5159-
(optional, string) Path to trusted CA certificate.
5190+
**`port`**
51605191

5161-
**`auth_by_ssl_client_certificate`**
5192+
(optional, integer) STOMP server's port number (default: 61614)
51625193

5163-
(optional, boolean) Whether to authenticate using TLS certificate. (Set to false for new *n6* auth.) Defaults to true.
5194+
**`exchange`**
5195+
5196+
(optional, string) STOMP *destination* to push at, e.g. ``"/exchange/_push"`` (which is default)
51645197

51655198
**`heartbeat`**
51665199

51675200
(optional, integer) Defaults to 60000.
51685201

5169-
**`message_hierarchical_output`**
5202+
**`ssl_ca_certificate`**
51705203

5171-
(optional, boolean) Defaults to false.
5204+
(optional, string) path to CA file, or empty string to load system's default CA certificates
51725205

5173-
**`message_jsondict_as_string`**
5206+
**`auth_by_ssl_client_certificate`**
51745207

5175-
(optional, boolean) Defaults to false.
5208+
(optional, boolean) default: true (note: false is needed for new *n6* auth)
51765209

5177-
**`message_with_type`**
5210+
**`ssl_client_certificate`**
51785211

5179-
(optional, boolean) Defaults to false.
5212+
(optional, string) Path to client certificate to use for TLS connections.
51805213

5181-
**`port`**
5214+
**`ssl_client_certificate_key`**
51825215

5183-
(optional, integer) Defaults to 61614.
5216+
(optional, string) Path to client private key to use for TLS connections.
51845217

5185-
**`server`**
5218+
**`username`**
51865219

5187-
(optional, string) Hostname of the STOMP server.
5220+
(optional, string) STOMP *login* (e.g., *n6* user login), used only if `auth_by_ssl_client_certificate` is false
51885221

5189-
**`single_key`**
5222+
**`password`**
51905223

5191-
(optional, string) Output only a single specified key. In case of `raw` key the data is base64 decoded. Defaults to null (output the whole message).
5224+
(optional, string) STOMP *passcode* (e.g., *n6* user API key), used only if `auth_by_ssl_client_certificate` is false
51925225

5193-
**`ssl_ca_certificate`**
5226+
**`message_hierarchical_output`**
51945227

5195-
(optional, string) Path to trusted CA certificate.
5228+
(optional, boolean) Defaults to false.
51965229

5197-
**`ssl_client_certificate`**
5230+
**`message_jsondict_as_string`**
51985231

5199-
(optional, string) Path to client certificate to use for TLS connections.
5232+
(optional, boolean) Defaults to false.
52005233

5201-
**`ssl_client_certificate_key`**
5234+
**`message_with_type`**
52025235

5203-
(optional, string) Path to client private key to use for TLS connections.
5236+
(optional, boolean) Defaults to false.
5237+
5238+
**`single_key`**
5239+
5240+
(optional, string) Output only a single specified key. In case of `raw` key the data is base64 decoded. Defaults to null (output the whole message).
52045241

52055242
---
52065243

docs/user/feeds.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -719,15 +719,15 @@ parameters:
719719
720720
### N6 Stomp Stream
721721
722-
N6 Collector - CERT.pl's N6 Collector - N6 feed via STOMP interface. Note that rate_limit does not apply for this bot as it is waiting for messages on a stream.
722+
N6 Collector - CERT.pl's *n6* Stream API feed (via STOMP interface). Note that 'rate_limit' does not apply to this bot, as it is waiting for messages on a stream.
723723
724724
**Public:** no
725725
726-
**Revision:** 2023-09-23
726+
**Revision:** 2023-10-08
727727
728728
**Documentation:** <https://n6.readthedocs.io/usage/streamapi/>
729729
730-
**Additional Information:** Contact cert.pl to get access to the feed.
730+
**Additional Information:** Contact CERT.pl to get access to the feed. Note that the configuration parameter values suggested here are suitable for the new *n6* Stream API variant (with authentication based on 'username' and 'password'); for this variant, typically you can leave the 'ssl_ca_certificate' parameter's value empty - then the system's default CA certificates will be used; however, if that does not work, you need to set 'ssl_ca_certificate' to the path to a file containing CA certificates eligible to verify "*.cert.pl" server certificates (to be found among the publicly available CA certs distributed with modern web browsers/OSes). Also, note that the 'server' parameter's value (for the *new API variant*) suggested here, "n6stream-new.cert.pl", is a temporary domain; ultimately, it will be changed back to "stream.cert.pl". When it comes to the *old API variant* (turned off in November 2023!), you need to have the 'server' parameter set to the name "n6stream.cert.pl", 'auth_by_ssl_client_certificate' set to true, 'ssl_ca_certificate' set to the path to a file containing the *n6*'s legacy self-signed CA certificate (which is stored in file "intelmq/bots/collectors/stomp/ca.pem"), and the parameters 'ssl_client_certificate' and 'ssl_client_certificate_key' set to the paths to your-*n6*-client-specific certificate and key files (note that the 'username' and 'password' parameters are then irrelevant and can be omitted).
731731
732732
733733
**Collector configuration**
@@ -736,14 +736,14 @@ N6 Collector - CERT.pl's N6 Collector - N6 feed via STOMP interface. Note that r
736736
module: intelmq.bots.collectors.stomp.collector
737737
parameters:
738738
auth_by_ssl_client_certificate: False
739-
exchange: {insert your exchange point as given by CERT.pl}
739+
exchange: {insert your STOMP *destination* to subscribe to, as given by CERT.pl, e.g. /exchange/my.example.org/*.*.*.*}
740740
name: N6 Stomp Stream
741-
password: {insert n6 user's API key}
741+
password: {insert your *n6* API key}
742742
port: 61614
743743
provider: CERT.PL
744-
server: n6stream.cert.pl
745-
ssl_ca_certificate: {insert path to CA file for CERT.pl's n6}
746-
username: {insert n6 user's login}
744+
server: n6stream-new.cert.pl
745+
ssl_ca_certificate:
746+
username: {insert your *n6* login, e.g. someuser@my.example.org}
747747
```
748748
749749
**Parser configuration**
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# SPDX-FileCopyrightText: 2017 Sebastian Wagner
22
# SPDX-License-Identifier: AGPL-3.0-or-later
33

4-
stomp.py>=4.1.8
4+
stomp.py>=4.1.12

intelmq/bots/collectors/stomp/collector.py

Lines changed: 32 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,19 @@
44

55
# -*- coding: utf-8 -*-
66

7-
from intelmq.lib.bot import CollectorBot
8-
from intelmq.lib.mixins import StompMixin
9-
107
try:
118
import stomp
12-
import stomp.exception
139
except ImportError:
1410
stomp = None
1511
else:
12+
import stomp.exception
13+
14+
from intelmq.lib.bot import CollectorBot
15+
from intelmq.lib.mixins import StompMixin
16+
17+
18+
if stomp is not None:
19+
1620
class StompListener(stomp.PrintingListener):
1721
"""
1822
the stomp listener gets called asynchronously for
@@ -74,17 +78,33 @@ def connect_and_subscribe(conn, logger, destination, start=False, connect_kwargs
7478
class StompCollectorBot(CollectorBot, StompMixin):
7579
"""Collect data from a STOMP Interface"""
7680
""" main class for the STOMP protocol collector """
77-
exchange: str = ''
81+
82+
server: str = 'n6stream.cert.pl'
7883
port: int = 61614
79-
server: str = "n6stream.cert.pl"
80-
auth_by_ssl_client_certificate: bool = True
81-
username: str = 'guest' # ignored if `auth_by_ssl_client_certificate` is true
82-
password: str = 'guest' # ignored if `auth_by_ssl_client_certificate` is true
83-
ssl_ca_certificate: str = 'ca.pem' # TODO pathlib.Path
84-
ssl_client_certificate: str = 'client.pem' # TODO pathlib.Path
85-
ssl_client_certificate_key: str = 'client.key' # TODO pathlib.Path
84+
exchange: str = ''
8685
heartbeat: int = 6000
8786

87+
# Note: the `ssl_ca_certificate` configuration parameter must be set:
88+
# * *either* to the server's CA certificate(s) file path,
89+
# * *or* to an empty string -- dictating that the SSL tools employed
90+
# by the `stomp.py`'s machinery will attempt to load the system’s
91+
# default CA certificates.
92+
# The latter, if applicable, is more convenient -- by avoiding the
93+
# need to manually update the CA certificate(s) file.
94+
ssl_ca_certificate: str = 'ca.pem' # <- TODO: change to '' (+ remove "ca.pem*" legacy files)
95+
# (^ TODO: could also be pathlib.Path)
96+
97+
auth_by_ssl_client_certificate: bool = True
98+
99+
# Used if `auth_by_ssl_client_certificate` is true (otherwise ignored):
100+
ssl_client_certificate: str = 'client.pem' # (cert file path)
101+
ssl_client_certificate_key: str = 'client.key' # (cert's key file path)
102+
# (^ TODO: could also be pathlib.Path)
103+
104+
# Used if `auth_by_ssl_client_certificate` is false (otherwise ignored):
105+
username: str = 'guest' # (STOMP auth *login*)
106+
password: str = 'guest' # (STOMP auth *passcode*)
107+
88108
_collector_empty_process: bool = True
89109
__conn = False # define here so shutdown method can check for it
90110

0 commit comments

Comments
 (0)