diff --git a/endpoints/notificationevent.py b/endpoints/notificationevent.py index cbba64fd0..94e795b64 100644 --- a/endpoints/notificationevent.py +++ b/endpoints/notificationevent.py @@ -112,6 +112,7 @@ def _build_summary(event_data): class VulnerabilityFoundEvent(NotificationEvent): CONFIG_LEVEL = 'level' + PRIORITY_KEY = 'priority' VULNERABILITY_KEY = 'vulnerability' MULTIPLE_VULNERABILITY_KEY = 'vulnerabilities' @@ -120,7 +121,8 @@ class VulnerabilityFoundEvent(NotificationEvent): return 'vulnerability_found' def get_level(self, event_data, notification_data): - priority = event_data[VulnerabilityFoundEvent.CONFIG_LEVEL]['priority'] + vuln_data = event_data[VulnerabilityFoundEvent.VULNERABILITY_KEY] + priority = vuln_data[VulnerabilityFoundEvent.PRIORITY_KEY] if priority == 'Defcon1' or priority == 'Critical': return 'error' @@ -138,6 +140,8 @@ class VulnerabilityFoundEvent(NotificationEvent): 'namespace_name': notification.repository.namespace_user.username, 'name': notification.repository.name, }) + + level = event_config.get(VulnerabilityFoundEvent.CONFIG_LEVEL, 'Critical') return build_event_data(repo, { 'tags': ['latest', 'prod', 'foo', 'bar', 'baz'], 'image': 'some-image-id', @@ -145,7 +149,7 @@ class VulnerabilityFoundEvent(NotificationEvent): 'id': 'CVE-FAKE-CVE', 'description': 'A futurist vulnerability', 'link': 'https://security-tracker.debian.org/tracker/CVE-FAKE-CVE', - 'priority': get_priority_for_index(event_config[VulnerabilityFoundEvent.CONFIG_LEVEL]) + 'priority': get_priority_for_index(level) }, }) @@ -167,10 +171,13 @@ class VulnerabilityFoundEvent(NotificationEvent): return actual_level_index <= filter_level_index def get_summary(self, event_data, notification_data): + vuln_key = VulnerabilityFoundEvent.VULNERABILITY_KEY + priority_key = VulnerabilityFoundEvent.PRIORITY_KEY + multiple_vulns = event_data.get(VulnerabilityFoundEvent.MULTIPLE_VULNERABILITY_KEY) if multiple_vulns is not None: - top_priority = multiple_vulns[0].get('priority', 'Unknown') - matching = [v for v in multiple_vulns if v.get('priority', 'Unknown') == top_priority] + top_priority = multiple_vulns[0].get(priority_key, 'Unknown') + matching = [v for v in multiple_vulns if v.get(priority_key, 'Unknown') == top_priority] msg = '%s %s' % (len(matching), top_priority) if len(matching) < len(multiple_vulns): @@ -180,7 +187,7 @@ class VulnerabilityFoundEvent(NotificationEvent): return msg % (event_data['repository'], len(event_data['tags'])) else: msg = '%s vulnerability detected in repository %s in %s tags' - return msg % (event_data['vulnerability']['priority'], event_data['repository'], + return msg % (event_data[vuln_key][priority_key], event_data['repository'], len(event_data['tags'])) diff --git a/endpoints/test/test_notificationevent.py b/endpoints/test/test_notificationevent.py new file mode 100644 index 000000000..65497f20c --- /dev/null +++ b/endpoints/test/test_notificationevent.py @@ -0,0 +1,33 @@ +import json + +from endpoints.notificationevent import NotificationEvent +from endpoints.test.fixtures import app, appconfig, database_uri, init_db_path, sqlitedb_file + +from util.morecollections import AttrDict + +def test_all_notifications(app): + # Create a test notification. + test_notification = AttrDict({ + 'repository': AttrDict({ + 'namespace_user': AttrDict(dict(username='foo')), + 'name': 'bar', + }), + 'event_config_json': json.dumps({ + 'level': 'low', + }), + }) + + for subc in NotificationEvent.__subclasses__(): + if subc.event_name() is not None: + # Create the notification event. + found = NotificationEvent.get_event(subc.event_name()) + sample_data = found.get_sample_data(test_notification) + + # Make sure all calls succeed. + notification_data = { + 'performer_data': {}, + } + + found.get_level(sample_data, notification_data) + found.get_summary(sample_data, notification_data) + found.get_message(sample_data, notification_data) diff --git a/events/vulnerability_found.html b/events/vulnerability_found.html index fd75df641..89cfd28a7 100644 --- a/events/vulnerability_found.html +++ b/events/vulnerability_found.html @@ -1,4 +1,8 @@ +{% if event_data.vulnerabilities %} +{{ event_data.vulnerabilities|length }} vulnerabilities were detected in tags +{% else %} A {{ event_data.vulnerability.priority }} vulnerability ({{ event_data.vulnerability.id }}) was detected in tags +{% endif %} {{ 'tags' | icon_image }} {% for tag in event_data.tags[0:3] %}{%if loop.index > 1 %}, {% endif %}{{ (event_data.repository, tag) | repository_tag_reference }}{% endfor %} {% if event_data.tags|length > 3 %}(and {{ event_data.tags|length - 3 }} more) {% endif %} in - repository {{ event_data.repository | repository_reference }} + repository {{ event_data.repository | repository_reference }} \ No newline at end of file diff --git a/test/test_secscan.py b/test/test_secscan.py index cc29e5d74..b5da8e2b6 100644 --- a/test/test_secscan.py +++ b/test/test_secscan.py @@ -355,6 +355,7 @@ class TestSecurityScanner(unittest.TestCase): event = VulnerabilityFoundEvent() msg = '1 Low and 1 more vulnerabilities were detected in repository devtable/simple in 2 tags' self.assertEquals(msg, event.get_summary(body['event_data'], {})) + self.assertEquals('info', event.get_level(body['event_data'], {})) else: self.assertIsNone(queue_item)