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

Commit

Permalink
Add AzWebAppHttp20Event plugin
Browse files Browse the repository at this point in the history
The plugin `AzWebAppHttp20Event` identifies an Azure web app with HTTP
version 2.0 disabled.

CIS recommends configuring web applications to use HTTP 2.0.
HTTP 2.0 has additional performance improvements on the head-of-line
blocking problem of old HTTP version, header compression, and
prioritization of requests. HTTP 2.0 no longer supports HTTP 1.1's
chunked transfer encoding mechanism, as it provides its own, more
efficient, mechanisms for data streaming.
  • Loading branch information
mitprasoon committed Mar 2, 2020
1 parent 2899c49 commit b548b7c
Show file tree
Hide file tree
Showing 4 changed files with 173 additions and 0 deletions.
1 change: 1 addition & 0 deletions cloudmarker/clouds/azwebapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ def _process_app_config(app_index, app, app_config,
'cloud_type': 'azure',
'record_type': 'web_app_config',
'https_only': app.get('https_only'),
'http20_enabled': app_config.get('http20_enabled'),
'min_tls_version': app_config.get('min_tls_version'),
'subscription_id': sub.get('subscription_id'),
'subscription_name': sub.get('display_name'),
Expand Down
99 changes: 99 additions & 0 deletions cloudmarker/events/azwebapphttp20event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
"""Microsoft web app HTTP 2.0 event.
This module defines the :class:`AzWebAppHttp20Event` class that identifies
if a web app is not using HTTP version 2.0. This plugin works on the web
apps config properties found in the ``ext`` bucket of ``web_app_config``
records.
"""


import logging

from cloudmarker import util

_log = logging.getLogger(__name__)


class AzWebAppHttp20Event:
"""Azure web app HTTP 2.0 event plugin."""

def __init__(self):
"""Create an instance of :class:`AzWebAppHttp20Event`."""

def eval(self, record):
"""Evaluate Azure web app to check for HTTP 2.0 config.
Arguments:
record (dict): A web app record.
Yields:
dict: An event record representing a web app with
HTTP 2.0 disabled.
"""
com = record.get('com', {})
if com is None:
return

if com.get('cloud_type') != 'azure':
return

ext = record.get('ext', {})
if ext is None:
return

if ext.get('record_type') != 'web_app_config':
return

if ext.get('http20_enabled'):
return

yield from _get_azure_web_app_http20_event(com, ext)

def done(self):
"""Perform cleanup work.
Currently, this method does nothing. This may change in future.
"""


def _get_azure_web_app_http20_event(com, ext):
"""Generate Web App HTTPS event.
Arguments:
com (dict): Azure web app record `com` bucket.
ext (dict): Azure web app record `ext` bucket.
Returns:
dict: An event record representing web apps with
HTTP version 2.0 disabled.
"""
friendly_cloud_type = util.friendly_string(com.get('cloud_type'))
reference = com.get('reference')
description = (
'{} web app {} has HTTP 2.0 disabled'
.format(friendly_cloud_type, reference)
)
recommendation = (
'Check {} web app {} and enable HTTP 2.0'
.format(friendly_cloud_type, reference)
)

event_record = {
# Preserve the extended properties from the web app
# record because they provide useful context to
# locate the web app that led to the event.
'ext': util.merge_dicts(ext, {
'record_type': 'web_app_http20_event'
}),
'com': {
'cloud_type': com.get('cloud_type'),
'record_type': 'web_app_http20_event',
'reference': reference,
'description': description,
'recommendation': recommendation,
}
}
_log.info('Generating web_app_http20_event; %r', event_record)
yield event_record
68 changes: 68 additions & 0 deletions cloudmarker/test/test_azwebapphttp20event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
"""Tests for AzWebAppHttp20Event plugin."""


import copy
import unittest

from cloudmarker.events import azwebapphttp20event

base_record = {
'ext': {
'record_type': 'web_app_config',
'cloud_type': 'azure',
'http20_enabled': True
},
'com': {
'cloud_type': 'azure'
}
}


class AzWebAppHttp20EventTest(unittest.TestCase):
"""Tests for AzWebAppHttp20Event plugin."""

def test_com_bucket_missing(self):
record = copy.deepcopy(base_record)
record['com'] = None
plugin = azwebapphttp20event.AzWebAppHttp20Event()
events = list(plugin.eval(record))
self.assertEqual(events, [])

def test_cloud_type_non_azure(self):
record = copy.deepcopy(base_record)
record['com']['cloud_type'] = 'non_azure'
plugin = azwebapphttp20event.AzWebAppHttp20Event()
events = list(plugin.eval(record))
self.assertEqual(events, [])

def test_ext_bucket_missing(self):
record = copy.deepcopy(base_record)
record['ext'] = None
plugin = azwebapphttp20event.AzWebAppHttp20Event()
events = list(plugin.eval(record))
self.assertEqual(events, [])

def test_record_type_non_web_app_config(self):
record = copy.deepcopy(base_record)
record['ext']['record_type'] = 'non_web_app_config'
plugin = azwebapphttp20event.AzWebAppHttp20Event()
events = list(plugin.eval(record))
self.assertEqual(events, [])

def test_http20_enabled(self):
record = copy.deepcopy(base_record)
record['ext']['http20_enabled'] = True
plugin = azwebapphttp20event.AzWebAppHttp20Event()
events = list(plugin.eval(record))
self.assertEqual(events, [])

def test_http20_disabled(self):
record = copy.deepcopy(base_record)
record['ext']['http20_enabled'] = False
plugin = azwebapphttp20event.AzWebAppHttp20Event()
events = list(plugin.eval(record))
self.assertEqual(len(events), 1)
self.assertEqual(events[0]['ext']['record_type'],
'web_app_http20_event')
self.assertEqual(events[0]['com']['record_type'],
'web_app_http20_event')
5 changes: 5 additions & 0 deletions pylama.ini
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,8 @@ ignore = R0201
ignore = R0201

# R0201 Method could be a function [pylint]

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

# R0201 Method could be a function [pylint]

0 comments on commit b548b7c

Please sign in to comment.