This repository has been archived by the owner on Aug 10, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add AzPostgresConnectionThrottlingEvent plugin
Added AzPostgresConnectionThrottlingEvent event plugin. This plugin evaluates Azure Postgres instances and generates an event of type `postgres_connection_throttling_event` if the `connection_throttling` is disabled. Enabling connection_throttling helps the PostgreSQL Database to set the verbosity of logged messages which in turn generates query and error logs with respect to concurrent connections, that could lead to a successful Denial of Service (DoS) attack by exhausting connection resources.
- Loading branch information
1 parent
83d5097
commit 3930bbe
Showing
5 changed files
with
209 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
107 changes: 107 additions & 0 deletions
107
cloudmarker/events/azpostgresconnectionthrottlingevent.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
"""Microsoft Azure Postgres Connection Throttling event. | ||
This module defines the :class:`AzPostgresConnectionThrottlingEvent` class | ||
that identifies Postgre SQL servers which connection throttling configuration | ||
disabled. This plugin works on the properties found in the ``com`` | ||
bucket of ``postgresql_server`` records. | ||
""" | ||
|
||
|
||
import logging | ||
|
||
from cloudmarker import util | ||
|
||
_log = logging.getLogger(__name__) | ||
|
||
|
||
class AzPostgresConnectionThrottlingEvent: | ||
"""Az Postgres connection throttling event plugin.""" | ||
|
||
def __init__(self): | ||
"""Create instance of :class:`AzPostgresConnectionThrottlingEvent`.""" | ||
|
||
def eval(self, record): | ||
"""Evaluate Postgres for connection throttling. | ||
Arguments: | ||
record (dict): An RDBMS record. | ||
Yields: | ||
dict: An event record representing a Postgres where | ||
connection throttling is disabled | ||
""" | ||
com = record.get('com', {}) | ||
if com is None: | ||
return | ||
|
||
if com.get('cloud_type') != 'azure': | ||
return | ||
|
||
if com.get('record_type') != 'rdbms': | ||
return | ||
|
||
ext = record.get('ext', {}) | ||
if ext is None: | ||
return | ||
|
||
if ext.get('record_type') != 'postgresql_server': | ||
return | ||
|
||
# True, None, missing key or any other value will not | ||
# genarated an event. An event will be generated only if | ||
# the value of `postgresql_server` is False. | ||
if ext.get('connection_throttling_enabled') is False: | ||
yield from _get_postgres_connection_throttling_disabled_event( | ||
com, ext) | ||
|
||
def done(self): | ||
"""Perform cleanup work. | ||
Currently, this method does nothing. This may change in future. | ||
""" | ||
|
||
|
||
def _get_postgres_connection_throttling_disabled_event(com, ext): | ||
"""Generate event for Postgres connection throttling disabled. | ||
Arguments: | ||
com (dict): Postgres record `com` bucket | ||
ext (dict): Postgres record `ext` bucket | ||
Returns: | ||
dict: An event record representing Postgres server | ||
with connection throttling disabled | ||
""" | ||
friendly_cloud_type = util.friendly_string(com.get('cloud_type')) | ||
friendly_rdbms_type = util.friendly_string(ext.get('record_type')) | ||
|
||
reference = com.get('reference') | ||
description = ( | ||
'{} {} {} has connection throttling disabled.' | ||
.format(friendly_cloud_type, friendly_rdbms_type, reference) | ||
) | ||
recommendation = ( | ||
'Check {} {} {} and enable connection throttling.' | ||
.format(friendly_cloud_type, friendly_rdbms_type, reference) | ||
) | ||
|
||
event_record = { | ||
# Preserve the extended properties from the RDBMS | ||
# record because they provide useful context to | ||
# locate the RDBMS that led to the event. | ||
'ext': util.merge_dicts(ext, { | ||
'record_type': 'postgres_connection_throttling_event' | ||
}), | ||
'com': { | ||
'cloud_type': com.get('cloud_type'), | ||
'record_type': 'postgres_connection_throttling_event', | ||
'reference': reference, | ||
'description': description, | ||
'recommendation': recommendation, | ||
} | ||
} | ||
|
||
_log.info('Generating postgres_connection_throttling_event; %r', | ||
event_record) | ||
yield event_record |
86 changes: 86 additions & 0 deletions
86
cloudmarker/test/test_azpostgresconnectionthrotthingevent.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
"""Tests for AzPostgresConnectionThrottlingEvent plugin.""" | ||
|
||
|
||
import copy | ||
import unittest | ||
|
||
from cloudmarker.events import azpostgresconnectionthrottlingevent | ||
|
||
base_record = { | ||
'com': { | ||
'cloud_type': 'azure', | ||
'record_type': 'rdbms', | ||
}, | ||
'ext': { | ||
'record_type': 'postgresql_server', | ||
'connection_throttling_enabled': False | ||
} | ||
} | ||
|
||
|
||
class AzPostgresConnectionThrottlingEventTest(unittest.TestCase): | ||
"""Tests for AzPostgresConnectionThrottlingEventTest plugin.""" | ||
|
||
def test_com_bucket_missing(self): | ||
record = copy.deepcopy(base_record) | ||
record['com'] = None | ||
plugin = azpostgresconnectionthrottlingevent. \ | ||
AzPostgresConnectionThrottlingEvent() | ||
events = list(plugin.eval(record)) | ||
self.assertEqual(events, []) | ||
|
||
def test_cloud_non_azure(self): | ||
record = copy.deepcopy(base_record) | ||
record['com']['cloud_type'] = 'non_azure' | ||
plugin = azpostgresconnectionthrottlingevent. \ | ||
AzPostgresConnectionThrottlingEvent() | ||
events = list(plugin.eval(record)) | ||
self.assertEqual(events, []) | ||
|
||
def test_record_type_non_rdbms(self): | ||
record = copy.deepcopy(base_record) | ||
record['com']['record_type'] = 'non_rdbms' | ||
plugin = azpostgresconnectionthrottlingevent. \ | ||
AzPostgresConnectionThrottlingEvent() | ||
events = list(plugin.eval(record)) | ||
self.assertEqual(events, []) | ||
|
||
def test_ext_bucket_missing(self): | ||
record = copy.deepcopy(base_record) | ||
record['ext'] = None | ||
plugin = azpostgresconnectionthrottlingevent. \ | ||
AzPostgresConnectionThrottlingEvent() | ||
events = list(plugin.eval(record)) | ||
self.assertEqual(events, []) | ||
|
||
def test_record_type_non_postgresql_server(self): | ||
record = copy.deepcopy(base_record) | ||
record['ext']['record_type'] = 'non_postgresql_server' | ||
plugin = azpostgresconnectionthrottlingevent. \ | ||
AzPostgresConnectionThrottlingEvent() | ||
events = list(plugin.eval(record)) | ||
self.assertEqual(events, []) | ||
|
||
def test_connection_throttling_enabled(self): | ||
record = copy.deepcopy(base_record) | ||
record['ext']['connection_throttling_enabled'] = True | ||
plugin = azpostgresconnectionthrottlingevent. \ | ||
AzPostgresConnectionThrottlingEvent() | ||
events = list(plugin.eval(record)) | ||
self.assertEqual(events, []) | ||
|
||
def test_connection_throttling_disenabled(self): | ||
record = copy.deepcopy(base_record) | ||
plugin = azpostgresconnectionthrottlingevent. \ | ||
AzPostgresConnectionThrottlingEvent() | ||
events = list(plugin.eval(record)) | ||
self.assertEqual(len(events), 1) | ||
self.assertEqual(events[0]['ext']['record_type'], | ||
'postgres_connection_throttling_event') | ||
self.assertEqual(events[0]['com']['cloud_type'], | ||
'azure') | ||
self.assertEqual(events[0]['com']['record_type'], | ||
'postgres_connection_throttling_event') | ||
self.assertTrue('reference' in events[0]['com']) | ||
self.assertIsNotNone(events[0]['com']['description']) | ||
self.assertIsNotNone(events[0]['com']['recommendation']) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters