From 004b24186bd2f0bb5a1ca2ea53648f529c88940c Mon Sep 17 00:00:00 2001 From: Teo Voinea Date: Wed, 8 Feb 2023 18:53:28 +0000 Subject: [PATCH 1/3] Add new command --- src/cli/onefuzz/api.py | 9 +++++++++ src/pytypes/onefuzztypes/requests.py | 1 + 2 files changed, 10 insertions(+) diff --git a/src/cli/onefuzz/api.py b/src/cli/onefuzz/api.py index d241284c8a..a276069cbd 100644 --- a/src/cli/onefuzz/api.py +++ b/src/cli/onefuzz/api.py @@ -859,6 +859,15 @@ def list( data=requests.NotificationSearch(container=container), ) + def get(self, notification_id: UUID_EXPANSION) -> List[models.Notification]: + """Get a notification""" + self.logger.debug("getting notification") + return self._req_model_list( + "GET", + models.Notification, + data=requests.NotificationSearch(notification_id=notification_id), + ) + class Tasks(Endpoint): """Interact with tasks""" diff --git a/src/pytypes/onefuzztypes/requests.py b/src/pytypes/onefuzztypes/requests.py index b2ceba3a44..f11f2255b7 100644 --- a/src/pytypes/onefuzztypes/requests.py +++ b/src/pytypes/onefuzztypes/requests.py @@ -52,6 +52,7 @@ class NotificationCreate(BaseRequest, NotificationConfig): class NotificationSearch(BaseRequest): container: Optional[List[Container]] + notification_id: Optional[UUID] class NotificationGet(BaseRequest): From aec6c016ff26333cfa9b0f3b7a0881e7fd601b42 Mon Sep 17 00:00:00 2001 From: Teo Voinea Date: Wed, 15 Feb 2023 14:04:27 +0000 Subject: [PATCH 2/3] Update remaining jinja templates and references to use scriban --- docs/notifications/github.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/notifications/github.md b/docs/notifications/github.md index a8b541b0bc..6be93787f1 100644 --- a/docs/notifications/github.md +++ b/docs/notifications/github.md @@ -3,7 +3,7 @@ OneFuzz can create or update [Github Issues](https://guides.github.com/features/issues/) upon creation of crash reports in OneFuzz managed [containers](../containers.md). -Nearly every field can be customized using [jinja2](https://jinja.palletsprojects.com/) +Nearly every field can be customized using [scriban](https://github.com/scriban/scriban) templates. There are multiple python objects provided via the template engine that can be used such that any arbitrary component can be used to flesh out the configuration: @@ -43,7 +43,7 @@ There are additional values that can be used in any template: "organization": "contoso", "repository": "sample-project", "title": "{{ report.executable }} - {{report.crash_site}}", - "body": "## Files\n\n* input: [{{ report.input_blob.name }}]({{ input_url }})\n* exe: [{{ report.executable }}]( {{ target_url }})\n* report: [{{ report_filename }}]({{ report_url }})\n\n## Repro\n\n `{{ repro_cmd }}`\n\n## Call Stack\n\n```{% for item in report.call_stack %}{{ item }}\n{% endfor %}```\n\n## ASAN Log\n\n```{{ report.asan_log }}```", + "body": "## Files\n\n* input: [{{ report.input_blob.name }}]({{ input_url }})\n* exe: [{{ report.executable }}]( {{ target_url }})\n* report: [{{ report_filename }}]({{ report_url }})\n\n## Repro\n\n `{{ repro_cmd }}`\n\n## Call Stack\n\n```{{ for item in report.call_stack }}{{ item }}\n{{ end }}```\n\n## ASAN Log\n\n```{{ report.asan_log }}```", "unique_search": { "field_match": ["title"], "string": "{{ report.executable }}" @@ -76,4 +76,4 @@ issues will be created and updated based on the reports. The OneFuzz SDK provides an example tool [fake-report.py](../../src/cli/examples/fake-report.py), which can be used to generate a synthetic crash report to verify the integration -is functional. \ No newline at end of file +is functional. From c718a4eee24fa15b89914aa2b3645febbd62bc53 Mon Sep 17 00:00:00 2001 From: Teo Voinea Date: Tue, 4 Apr 2023 13:24:32 +0000 Subject: [PATCH 3/3] Do not enforce that key exists in dictionary when doing strict validation --- .../notifications/NotificationsBase.cs | 2 +- .../JinjaToScribanMigrationTests.cs | 21 +++++++++++++++++++ 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/ApiService/ApiService/onefuzzlib/notifications/NotificationsBase.cs b/src/ApiService/ApiService/onefuzzlib/notifications/NotificationsBase.cs index fdcb88d84b..ccd5cfe946 100644 --- a/src/ApiService/ApiService/onefuzzlib/notifications/NotificationsBase.cs +++ b/src/ApiService/ApiService/onefuzzlib/notifications/NotificationsBase.cs @@ -138,7 +138,7 @@ public async Async.Task Render(string templateString, Uri instanceUrl, b true => new TemplateContext { EnableRelaxedFunctionAccess = false, EnableRelaxedIndexerAccess = false, - EnableRelaxedMemberAccess = false, + EnableRelaxedMemberAccess = true, EnableRelaxedTargetAccess = false }, _ => new TemplateContext() diff --git a/src/ApiService/IntegrationTests/JinjaToScribanMigrationTests.cs b/src/ApiService/IntegrationTests/JinjaToScribanMigrationTests.cs index f4a9acfa40..90607f35db 100644 --- a/src/ApiService/IntegrationTests/JinjaToScribanMigrationTests.cs +++ b/src/ApiService/IntegrationTests/JinjaToScribanMigrationTests.cs @@ -362,6 +362,12 @@ public async Async.Task Access_WithoutAuthorization_IsRejected() { result.StatusCode.Should().Be(System.Net.HttpStatusCode.BadRequest); } + [Fact] + public async Async.Task Do_Not_Enforce_Key_Exists_In_Strict_Validation() { + (await JinjaTemplateAdapter.IsValidScribanNotificationTemplate(Context, Logger, ValidScribanAdoTemplate())) + .Should().BeTrue(); + } + private async Async.Task ConfigureAuth() { await Context.InsertAll( new InstanceConfig(Context.ServiceConfiguration.OneFuzzInstanceName!) { Admins = new[] { _userObjectId } } // needed for admin check @@ -412,4 +418,19 @@ private static GithubIssuesTemplate MigratableGithubTemplate() { private static TeamsTemplate GetTeamsTemplate() { return new TeamsTemplate(new SecretData(new SecretValue("https://example.com"))); } + + private static AdoTemplate ValidScribanAdoTemplate() { + return new AdoTemplate( + new Uri("http://example.com"), + new SecretData(new SecretValue("some secret")), + "{{ if task.tags.project }} blah {{ end }}", + string.Empty, + Array.Empty().ToList(), + new Dictionary(), + new ADODuplicateTemplate( + Array.Empty().ToList(), + new Dictionary(), + new Dictionary() + )); + } }