Skip to content

Commit

Permalink
Merge pull request #1341 from jertel/jertel/fixsmtpcert
Browse files Browse the repository at this point in the history
Use SSLContext for Python 3.12; fixes #1339
  • Loading branch information
nsano-rururu authored Dec 8, 2023
2 parents 5745c1f + 3f548c3 commit 0716fd3
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 39 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
__pycache__/
*.pyc
virtualenv_run/
.venv
.venv*
*.egg-info/
dist/
venv/
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
- [IRIS] Make parameter iris_customer_id optional with default value - [1334](https://github.com/jertel/elastalert2/pull/1334) @malinkinsa
- (Re)Implement `skip_invalid` to continue loading rules if one is invalid - [#1338](https://github.com/jertel/elastalert2/pull/1338) - @jertel
- [Docs] Refactor the docs structure for improved ease-of-use - [#1337](https://github.com/jertel/elastalert2/pull/1337) - @jertel
- [Email] Refactor SMTP cert/key usage to support Python 3.12 - [#1341](https://github.com/jertel/elastalert2/pull/1341) - @jertel

# 2.15.0

Expand Down
2 changes: 1 addition & 1 deletion docs/source/alerts.rst
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ Example usage::
jira_alert_owner: $owner$


.. _alerts:
.. _alert_types:

Alert Types
===========
Expand Down
2 changes: 1 addition & 1 deletion docs/source/ruletypes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ or loaded from a module. For loading from a module, the type should be specified
alert
^^^^^

``alert``: The ``Alerter`` type to use. This may be one or more of the built in alerts, see :ref:`Alert Types <alerts>` section below for more information,
``alert``: The ``Alerter`` type to use. This may be one or more of the built in alerts, see :ref:`Alert Types <alert_types>` section below for more information,
or loaded from a module. For loading from a module, the alert should be specified as ``module.file.AlertName``. (Required, string or list, no default)

Optional Settings
Expand Down
2 changes: 1 addition & 1 deletion docs/source/running_elastalert.rst
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ information. If no filters are desired, it should be specified as an empty list:
``filter: []``

``alert`` is a list of alerts to run on each match. For more information on
alert types, see :ref:`Alerts <alerts>`. The email alert requires an SMTP server
alert types, see :ref:`Alert Types <alert_types>`. The email alert requires an SMTP server
for sending mail. By default, it will attempt to use localhost. This can be
changed with the ``smtp_host`` option.

Expand Down
12 changes: 9 additions & 3 deletions elastalert/alerters/email.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import os
import ssl

from elastalert.alerts import Alerter
from elastalert.util import elastalert_logger, lookup_es_key, EAException
Expand Down Expand Up @@ -91,12 +92,17 @@ def alert(self, matches):
to_addr = to_addr + self.rule['bcc']

try:
ssl_context = None
if self.smtp_cert_file:
ssl_context = ssl.create_default_context()
ssl_context.load_cert_chain(certfile=self.smtp_cert_file, keyfile=self.smtp_key_file)

if self.smtp_ssl:
if self.smtp_port:
self.smtp = SMTP_SSL(self.smtp_host, self.smtp_port, keyfile=self.smtp_key_file, certfile=self.smtp_cert_file)
self.smtp = SMTP_SSL(self.smtp_host, self.smtp_port, context=ssl_context)
else:
# default port : 465
self.smtp = SMTP_SSL(self.smtp_host, keyfile=self.smtp_key_file, certfile=self.smtp_cert_file)
self.smtp = SMTP_SSL(self.smtp_host, context=ssl_context)
else:
if self.smtp_port:
self.smtp = SMTP(self.smtp_host, self.smtp_port)
Expand All @@ -105,7 +111,7 @@ def alert(self, matches):
self.smtp = SMTP(self.smtp_host)
self.smtp.ehlo()
if self.smtp.has_extn('STARTTLS'):
self.smtp.starttls(keyfile=self.smtp_key_file, certfile=self.smtp_cert_file)
self.smtp.starttls(context=ssl_context)
if 'smtp_auth_file' in self.rule:
self.smtp.login(self.user, self.password)
except (SMTPException, error) as e:
Expand Down
66 changes: 34 additions & 32 deletions tests/alerters/email_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def test_email(caplog):
expected = [mock.call('localhost'),
mock.call().ehlo(),
mock.call().has_extn('STARTTLS'),
mock.call().starttls(certfile=None, keyfile=None),
mock.call().starttls(context=None),
mock.call().sendmail(
mock.ANY,
[
Expand Down Expand Up @@ -103,7 +103,7 @@ def test_email_with_unicode_strings():
expected = [mock.call('localhost'),
mock.call().ehlo(),
mock.call().has_extn('STARTTLS'),
mock.call().starttls(certfile=None, keyfile=None),
mock.call().starttls(context=None),
mock.call().sendmail(mock.ANY, ['[email protected]'], mock.ANY),
mock.call().quit()]
assert mock_smtp.mock_calls == expected
Expand Down Expand Up @@ -139,7 +139,7 @@ def test_email_with_auth():
expected = [mock.call('localhost'),
mock.call().ehlo(),
mock.call().has_extn('STARTTLS'),
mock.call().starttls(certfile=None, keyfile=None),
mock.call().starttls(context=None),
mock.call().login('someone', 'hunter2'),
mock.call().sendmail(
mock.ANY,
Expand Down Expand Up @@ -168,28 +168,30 @@ def test_email_with_cert_key():
'smtp_key_file': 'dummy/client.key',
'rule_file': '/tmp/foo.yaml'
}
with mock.patch('elastalert.alerters.email.SMTP') as mock_smtp:
with mock.patch('elastalert.alerts.read_yaml') as mock_open:
mock_open.return_value = {'user': 'someone', 'password': 'hunter2'}
mock_smtp.return_value = mock.Mock()
alert = EmailAlerter(rule)
with mock.patch('ssl.SSLContext') as mock_ctx:
with mock.patch('elastalert.alerters.email.SMTP') as mock_smtp:
with mock.patch('elastalert.alerts.read_yaml') as mock_open:
mock_open.return_value = {'user': 'someone', 'password': 'hunter2'}
mock_smtp.return_value = mock.Mock()
alert = EmailAlerter(rule)

alert.alert([{'test_term': 'test_value'}])
expected = [mock.call('localhost'),
mock.call().ehlo(),
mock.call().has_extn('STARTTLS'),
mock.call().starttls(certfile='dummy/cert.crt', keyfile='dummy/client.key'),
mock.call().login('someone', 'hunter2'),
mock.call().sendmail(
mock.ANY,
[
'[email protected]',
'[email protected]'
],
mock.ANY
),
mock.call().quit()]
assert mock_smtp.mock_calls == expected
alert.alert([{'test_term': 'test_value'}])
expected = [mock.call('localhost'),
mock.call().ehlo(),
mock.call().has_extn('STARTTLS'),
mock.call().starttls(context=mock.ANY),
mock.call().login('someone', 'hunter2'),
mock.call().sendmail(
mock.ANY,
[
'[email protected]',
'[email protected]'
],
mock.ANY
),
mock.call().quit()]
assert mock_smtp.mock_calls == expected
assert mock.call().load_cert_chain(certfile='dummy/cert.crt', keyfile='dummy/client.key') in mock_ctx.mock_calls


def test_email_with_cc():
Expand All @@ -210,7 +212,7 @@ def test_email_with_cc():
expected = [mock.call('localhost'),
mock.call().ehlo(),
mock.call().has_extn('STARTTLS'),
mock.call().starttls(certfile=None, keyfile=None),
mock.call().starttls(context=None),
mock.call().sendmail(
mock.ANY,
[
Expand Down Expand Up @@ -249,7 +251,7 @@ def test_email_with_bcc():
expected = [mock.call('localhost'),
mock.call().ehlo(),
mock.call().has_extn('STARTTLS'),
mock.call().starttls(certfile=None, keyfile=None),
mock.call().starttls(context=None),
mock.call().sendmail(
mock.ANY,
[
Expand Down Expand Up @@ -289,7 +291,7 @@ def test_email_with_cc_and_bcc():
expected = [mock.call('localhost'),
mock.call().ehlo(),
mock.call().has_extn('STARTTLS'),
mock.call().starttls(certfile=None, keyfile=None),
mock.call().starttls(context=None),
mock.call().sendmail(
mock.ANY,
[
Expand Down Expand Up @@ -334,7 +336,7 @@ def test_email_with_args():
expected = [mock.call('localhost'),
mock.call().ehlo(),
mock.call().has_extn('STARTTLS'),
mock.call().starttls(certfile=None, keyfile=None),
mock.call().starttls(context=None),
mock.call().sendmail(
mock.ANY,
[
Expand Down Expand Up @@ -498,7 +500,7 @@ def test_email_smtp_port():
expected = [mock.call('localhost', 35),
mock.call().ehlo(),
mock.call().has_extn('STARTTLS'),
mock.call().starttls(certfile=None, keyfile=None),
mock.call().starttls(context=None),
mock.call().sendmail(
mock.ANY,
[
Expand Down Expand Up @@ -537,7 +539,7 @@ def test_email_smtp_ssl_true():

alert = EmailAlerter(rule)
alert.alert([{'test_term': 'test_value'}])
expected = [mock.call('localhost', certfile=None, keyfile=None),
expected = [mock.call('localhost', context=None),
mock.call().sendmail(
mock.ANY,
[
Expand Down Expand Up @@ -577,7 +579,7 @@ def test_email_smtp_ssl_true_and_smtp_port():

alert = EmailAlerter(rule)
alert.alert([{'test_term': 'test_value'}])
expected = [mock.call('localhost', 455, certfile=None, keyfile=None),
expected = [mock.call('localhost', 455, context=None),
mock.call().sendmail(
mock.ANY,
[
Expand Down Expand Up @@ -640,7 +642,7 @@ def test_email_format_html():

alert = EmailAlerter(rule)
alert.alert([{'test_term': 'test_value'}])
expected = [mock.call('localhost', 455, certfile=None, keyfile=None),
expected = [mock.call('localhost', 455, context=None),
mock.call().sendmail(
mock.ANY,
[
Expand Down

0 comments on commit 0716fd3

Please sign in to comment.