From d385f32131befab602e58c4085fa50624f5b4d52 Mon Sep 17 00:00:00 2001 From: Brian Caswell Date: Thu, 18 Feb 2021 20:05:29 -0500 Subject: [PATCH 1/5] add instance information to webhooks --- docs/webhook_events.md | 13 +++++++++++++ src/api-service/__app__/onefuzzlib/events.py | 8 +++++++- src/pytypes/extra/generate-docs.py | 2 ++ src/pytypes/onefuzztypes/events.py | 2 ++ 4 files changed, 24 insertions(+), 1 deletion(-) diff --git a/docs/webhook_events.md b/docs/webhook_events.md index d7cfe1edc6..0ec8c6d21b 100644 --- a/docs/webhook_events.md +++ b/docs/webhook_events.md @@ -15,6 +15,8 @@ Each event will be submitted via HTTP POST to the user provided URL. }, "event_id": "00000000-0000-0000-0000-000000000000", "event_type": "ping", + "instance_id": "00000000-0000-0000-0000-000000000000", + "instance_name": "example", "webhook_id": "00000000-0000-0000-0000-000000000000" } ``` @@ -2927,6 +2929,15 @@ Each event will be submitted via HTTP POST to the user provided URL. "event_type": { "$ref": "#/definitions/EventType" }, + "instance_id": { + "format": "uuid", + "title": "Instance Id", + "type": "string" + }, + "instance_name": { + "title": "Instance Name", + "type": "string" + }, "webhook_id": { "format": "uuid", "title": "Webhook Id", @@ -2936,6 +2947,8 @@ Each event will be submitted via HTTP POST to the user provided URL. "required": [ "event_type", "event", + "instance_id", + "instance_name", "webhook_id" ], "title": "WebhookMessage", diff --git a/src/api-service/__app__/onefuzzlib/events.py b/src/api-service/__app__/onefuzzlib/events.py index efe3220a3d..f89e7dd867 100644 --- a/src/api-service/__app__/onefuzzlib/events.py +++ b/src/api-service/__app__/onefuzzlib/events.py @@ -10,6 +10,7 @@ from onefuzztypes.events import Event, EventMessage, get_event_type +from .azure.creds import get_instance_id, get_instance_name from .webhooks import Webhook EVENTS: Queue = Queue() @@ -35,6 +36,11 @@ def get_events() -> Optional[str]: def send_event(event: Event) -> None: event_type = get_event_type(event) logging.info("sending event: %s - %s", event_type, event) - event_message = EventMessage(event_type=event_type, event=event) + event_message = EventMessage( + event_type=event_type, + event=event, + instance_id=get_instance_id(), + instance_name=get_instance_name(), + ) EVENTS.put(event_message) Webhook.send_event(event_message) diff --git a/src/pytypes/extra/generate-docs.py b/src/pytypes/extra/generate-docs.py index c92b2f1401..60954f14fd 100755 --- a/src/pytypes/extra/generate-docs.py +++ b/src/pytypes/extra/generate-docs.py @@ -210,6 +210,8 @@ def main(): event_id=UUID(int=0), event_type=EventType.ping, event=EventPing(ping_id=UUID(int=0)), + instance_id=UUID(int=0), + instance_name="example", ) layer( diff --git a/src/pytypes/onefuzztypes/events.py b/src/pytypes/onefuzztypes/events.py index fb6207fb67..6587ddab1f 100644 --- a/src/pytypes/onefuzztypes/events.py +++ b/src/pytypes/onefuzztypes/events.py @@ -223,3 +223,5 @@ class EventMessage(BaseEvent): event_id: UUID = Field(default_factory=uuid4) event_type: EventType event: Event + instance_id: UUID + instance_name: str From 1d8ef3937990912ab2e08e796d06ba3af0c5a03c Mon Sep 17 00:00:00 2001 From: Brian Caswell Date: Fri, 19 Feb 2021 10:17:41 -0500 Subject: [PATCH 2/5] add instance_id and instance_name to more places --- .../__app__/onefuzzlib/webhooks.py | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/api-service/__app__/onefuzzlib/webhooks.py b/src/api-service/__app__/onefuzzlib/webhooks.py index 5f3d99a58c..34e4583d9f 100644 --- a/src/api-service/__app__/onefuzzlib/webhooks.py +++ b/src/api-service/__app__/onefuzzlib/webhooks.py @@ -21,6 +21,7 @@ from pydantic import BaseModel from .__version__ import __version__ +from .azure.creds import get_instance_id, get_instance_name from .azure.queue import queue_object from .azure.storage import StorageType from .orm import ORMMixin @@ -169,13 +170,22 @@ def _add_event(self, event_message: EventMessage) -> None: event_id=event_message.event_id, event_type=event_message.event_type, event=event_message.event, + instance_id=event_message.instance_id, + instance_name=event_message.instance_name, ) message.save() message.queue_webhook() def ping(self) -> EventPing: ping = EventPing(ping_id=uuid4()) - self._add_event(EventMessage(event_type=EventType.ping, event=ping)) + self._add_event( + EventMessage( + event_type=EventType.ping, + event=ping, + instance_id=get_instance_id(), + instance_name=get_instance_name(), + ) + ) return ping def send(self, message_log: WebhookMessageLog) -> bool: @@ -213,7 +223,12 @@ def build_message( ) -> Tuple[bytes, Optional[str]]: data = ( WebhookMessage( - webhook_id=webhook_id, event_id=event_id, event_type=event_type, event=event + webhook_id=webhook_id, + event_id=event_id, + event_type=event_type, + event=event, + instance_id=get_instance_id(), + instance_name=get_instance_name(), ) .json(sort_keys=True, exclude_none=True) .encode() From 48596375a51f574901cec05351c21bc8c80b28c8 Mon Sep 17 00:00:00 2001 From: Brian Caswell Date: Fri, 19 Feb 2021 11:47:45 -0500 Subject: [PATCH 3/5] update unittest to mock out get_instance_id and get_instance_name --- src/api-service/tests/test_webhook_hmac.py | 25 ++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/api-service/tests/test_webhook_hmac.py b/src/api-service/tests/test_webhook_hmac.py index 8298148672..71b3bf00c0 100644 --- a/src/api-service/tests/test_webhook_hmac.py +++ b/src/api-service/tests/test_webhook_hmac.py @@ -3,23 +3,33 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. +import os import unittest +from unittest.mock import MagicMock, patch from uuid import UUID from onefuzztypes.events import EventPing, EventType -from __app__.onefuzzlib.webhooks import build_message - class TestWebhookHmac(unittest.TestCase): - def test_webhook_hmac(self) -> None: + @patch.dict(os.environ, {"ONEFUZZ_INSTANCE_NAME": "example"}) + @patch("__app__.onefuzzlib.azure.creds.get_instance_id") + def test_webhook_hmac(self, mock_id: MagicMock) -> None: + mock_id.return_value = UUID(int=3) + + # late import to enable the patch to function + from __app__.onefuzzlib.webhooks import build_message + webhook_id = UUID(int=0) event_id = UUID(int=1) event_type = EventType.ping event = EventPing(ping_id=UUID(int=2)) data, digest = build_message( - webhook_id=webhook_id, event_id=event_id, event_type=event_type, event=event + webhook_id=webhook_id, + event_id=event_id, + event_type=event_type, + event=event, ) expected = ( @@ -27,16 +37,19 @@ def test_webhook_hmac(self) -> None: b'"event": {"ping_id": "00000000-0000-0000-0000-000000000002"}, ' b'"event_id": "00000000-0000-0000-0000-000000000001", ' b'"event_type": "ping", ' + b'"instance_id": "00000000-0000-0000-0000-000000000003", ' + b'"instance_name": "example", ' b'"webhook_id": "00000000-0000-0000-0000-000000000000"' b"}" ) expected_digest = ( - "3502f83237ce006b7f6cfa40b89c0295009e3ccb0a1e62ce1d689700c2c6e698" - "61c0de81e011495c2ca89fbf99485b841cee257bcfba326a3edc66f39dc1feec" + "2f0610d708d9938dc053200cd2242b4cca4e9bb7227e5e662f28307f57c7fc9b" + "d1ffcab6fff9f409b3fb856db4f358be9078ec0b64874efac2b8f065211e2a14" ) print(repr(expected)) + print(repr(data)) self.assertEqual(data, expected) self.assertEqual(digest, None) From ba355a3486fe35890a3e13cb7cb00f68b90a42c5 Mon Sep 17 00:00:00 2001 From: Brian Caswell Date: Fri, 19 Feb 2021 11:59:54 -0500 Subject: [PATCH 4/5] use patch to mock get_instance_name rather than patch the env --- src/api-service/tests/test_webhook_hmac.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/api-service/tests/test_webhook_hmac.py b/src/api-service/tests/test_webhook_hmac.py index 71b3bf00c0..7bd91c8365 100644 --- a/src/api-service/tests/test_webhook_hmac.py +++ b/src/api-service/tests/test_webhook_hmac.py @@ -3,7 +3,6 @@ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. -import os import unittest from unittest.mock import MagicMock, patch from uuid import UUID @@ -12,9 +11,10 @@ class TestWebhookHmac(unittest.TestCase): - @patch.dict(os.environ, {"ONEFUZZ_INSTANCE_NAME": "example"}) @patch("__app__.onefuzzlib.azure.creds.get_instance_id") - def test_webhook_hmac(self, mock_id: MagicMock) -> None: + @patch("__app__.onefuzzlib.azure.creds.get_instance_name") + def test_webhook_hmac(self, mock_name: MagicMock, mock_id: MagicMock) -> None: + mock_name.return_value = "example" mock_id.return_value = UUID(int=3) # late import to enable the patch to function From 8ff998990b85d9c65d494e044cd4eb717ce0ad73 Mon Sep 17 00:00:00 2001 From: Brian Caswell Date: Fri, 19 Feb 2021 12:40:48 -0500 Subject: [PATCH 5/5] mock out the imported version, rather than the global version to help with `pytest ./tests` case --- src/api-service/tests/test_webhook_hmac.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api-service/tests/test_webhook_hmac.py b/src/api-service/tests/test_webhook_hmac.py index 7bd91c8365..a49d9a3192 100644 --- a/src/api-service/tests/test_webhook_hmac.py +++ b/src/api-service/tests/test_webhook_hmac.py @@ -11,8 +11,8 @@ class TestWebhookHmac(unittest.TestCase): - @patch("__app__.onefuzzlib.azure.creds.get_instance_id") - @patch("__app__.onefuzzlib.azure.creds.get_instance_name") + @patch("__app__.onefuzzlib.webhooks.get_instance_id") + @patch("__app__.onefuzzlib.webhooks.get_instance_name") def test_webhook_hmac(self, mock_name: MagicMock, mock_id: MagicMock) -> None: mock_name.return_value = "example" mock_id.return_value = UUID(int=3)