Skip to content
This repository has been archived by the owner on Aug 10, 2024. It is now read-only.

Commit

Permalink
Add AzPostgresConnectionThrottlingEvent plugin
Browse files Browse the repository at this point in the history
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
mitprasoon committed Feb 29, 2020
1 parent 83d5097 commit 3930bbe
Show file tree
Hide file tree
Showing 5 changed files with 209 additions and 0 deletions.
3 changes: 3 additions & 0 deletions cloudmarker/baseconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@
azpostgreslogdurationevent:
plugin: cloudmarker.events.azpostgreslogdurationevent.AzPostgresLogDurationEvent
azpostgresconnectionthrottlingevent:
plugin: cloudmarker.events.azpostgresconnectionthrottlingevent.AzPostgresConnectionThrottlingEvent
mockevent:
plugin: cloudmarker.events.mockevent.MockEvent
Expand Down
107 changes: 107 additions & 0 deletions cloudmarker/events/azpostgresconnectionthrottlingevent.py
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 cloudmarker/test/test_azpostgresconnectionthrotthingevent.py
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'])
8 changes: 8 additions & 0 deletions docs/api/cloudmarker.events.rst
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ cloudmarker.events.azpostgreslogdurationevent module
:undoc-members:
:show-inheritance:

cloudmarker.events.azpostgresconnectionthrottlingevent module
-------------------------------------------------------------

.. automodule:: cloudmarker.events.azpostgresconnectionthrottlingevent
:members:
:undoc-members:
:show-inheritance:

cloudmarker.events.azsqldatabasetdeevent module
-----------------------------------------------

Expand Down
5 changes: 5 additions & 0 deletions pylama.ini
Original file line number Diff line number Diff line change
Expand Up @@ -216,3 +216,8 @@ ignore = R0201
ignore = R0201

# R0201 Method could be a function [pylint]

[pylama:cloudmarker/events/azpostgresconnectionthrottlingevent.py]
ignore = R0201

# R0201 Method could be a function [pylint]

0 comments on commit 3930bbe

Please sign in to comment.