From fe28d2b60810d80a34f356ea9b612eaf348555e6 Mon Sep 17 00:00:00 2001 From: Mariana Rios Flores Date: Tue, 9 Jun 2020 13:18:41 -0700 Subject: [PATCH 1/4] sanitize body --- .../src/Azure.Core.TestFramework.csproj | 1 + .../src/RecordedTestSanitizer.cs | 19 +++++++ .../FormTrainingClientLiveTests.cs | 7 +-- .../FormRecognizerRecordedTestSanitizer.cs | 6 +++ .../CopyModelError.json | 52 +++++++++++++++++++ .../CopyModelErrorAsync.json | 52 +++++++++++++++++++ .../GetCopyAuthorization.json | 42 +++++++++++++++ .../GetCopyAuthorizationAsync.json | 42 +++++++++++++++ ...lizeDeserializeCopyAuthorizationAsync.json | 42 +++++++++++++++ ...eserializeCopyAuthorizationAsyncAsync.json | 42 +++++++++++++++ 10 files changed, 300 insertions(+), 5 deletions(-) create mode 100644 sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/CopyModelError.json create mode 100644 sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/CopyModelErrorAsync.json create mode 100644 sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/GetCopyAuthorization.json create mode 100644 sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/GetCopyAuthorizationAsync.json create mode 100644 sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/SerializeDeserializeCopyAuthorizationAsync.json create mode 100644 sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/SerializeDeserializeCopyAuthorizationAsyncAsync.json diff --git a/sdk/core/Azure.Core.TestFramework/src/Azure.Core.TestFramework.csproj b/sdk/core/Azure.Core.TestFramework/src/Azure.Core.TestFramework.csproj index 49f96cf34603..e3fa5db6a1c3 100644 --- a/sdk/core/Azure.Core.TestFramework/src/Azure.Core.TestFramework.csproj +++ b/sdk/core/Azure.Core.TestFramework/src/Azure.Core.TestFramework.csproj @@ -5,6 +5,7 @@ + diff --git a/sdk/core/Azure.Core.TestFramework/src/RecordedTestSanitizer.cs b/sdk/core/Azure.Core.TestFramework/src/RecordedTestSanitizer.cs index 5b8e94738c6a..b147eaf8ea17 100644 --- a/sdk/core/Azure.Core.TestFramework/src/RecordedTestSanitizer.cs +++ b/sdk/core/Azure.Core.TestFramework/src/RecordedTestSanitizer.cs @@ -5,12 +5,15 @@ using System.Globalization; using System.Linq; using System.Text; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; namespace Azure.Core.TestFramework { public class RecordedTestSanitizer { public const string SanitizeValue = "Sanitized"; + public static List JsonPathSanitizers = new List(); private static readonly string[] s_sanitizeValueArray = { SanitizeValue }; private static readonly string[] s_sanitizedHeaders = { "Authorization" }; @@ -33,6 +36,11 @@ public virtual void SanitizeHeaders(IDictionary headers) public virtual string SanitizeTextBody(string contentType, string body) { + foreach (var jsonPath in JsonPathSanitizers) + { + return SanitizeJsonBody(body, jsonPath); + } + return body; } @@ -41,6 +49,17 @@ public virtual byte[] SanitizeBody(string contentType, byte[] body) return body; } + public virtual string SanitizeJsonBody(string body, string jsonPath) + { + var jsonO = JObject.Parse(body); + + foreach (JToken token in jsonO.SelectTokens(jsonPath)) + { + token.Replace(JToken.FromObject(SanitizeValue)); + } + return JsonConvert.SerializeObject(jsonO); + } + public virtual string SanitizeVariable(string variableName, string environmentVariableValue) => environmentVariableValue; public virtual void SanitizeBody(RecordEntryMessage message) diff --git a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/FormTrainingClient/FormTrainingClientLiveTests.cs b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/FormTrainingClient/FormTrainingClientLiveTests.cs index 4922a1e89498..e9711d22abb2 100644 --- a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/FormTrainingClient/FormTrainingClientLiveTests.cs +++ b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/FormTrainingClient/FormTrainingClientLiveTests.cs @@ -220,21 +220,19 @@ public async Task CopyModel() } [Test] - [Ignore("Tracked by issue: https://github.com/Azure/azure-sdk-for-net/issues/12193")] - public async Task CopyModelError() + public void CopyModelError() { var sourceClient = CreateInstrumentedFormTrainingClient(); var targetClient = CreateInstrumentedFormTrainingClient(); var resourceID = TestEnvironment.TargetResourceId; var region = TestEnvironment.TargetResourceRegion; - CopyAuthorization targetAuth = await targetClient.GetCopyAuthorizationAsync(resourceID, region); + CopyAuthorization targetAuth = CopyAuthorization.FromJson("{\"modelId\":\"328c3b7d - a563 - 4ba2 - 8c2f - 2f26d664486a\",\"accessToken\":\"5b5685e4 - 2f24 - 4423 - ab18 - 000000000000\",\"expirationDateTimeTicks\":1591932653,\"resourceId\":\"resourceId\",\"resourceRegion\":\"westcentralus\"}"); Assert.ThrowsAsync(async () => await sourceClient.StartCopyModelAsync("00000000-0000-0000-0000-000000000000", targetAuth)); } [Test] - [Ignore("Tracked by issue: https://github.com/Azure/azure-sdk-for-net/issues/12193")] public async Task GetCopyAuthorization() { var targetClient = CreateInstrumentedFormTrainingClient(); @@ -251,7 +249,6 @@ public async Task GetCopyAuthorization() } [Test] - [Ignore("Tracked by issue: https://github.com/Azure/azure-sdk-for-net/issues/12193")] public async Task SerializeDeserializeCopyAuthorizationAsync() { var targetClient = CreateInstrumentedFormTrainingClient(); diff --git a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/Infrastructure/FormRecognizerRecordedTestSanitizer.cs b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/Infrastructure/FormRecognizerRecordedTestSanitizer.cs index 14671e1fa8bc..0723bbf6658d 100644 --- a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/Infrastructure/FormRecognizerRecordedTestSanitizer.cs +++ b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/Infrastructure/FormRecognizerRecordedTestSanitizer.cs @@ -10,6 +10,12 @@ public class FormRecognizerRecordedTestSanitizer : RecordedTestSanitizer { private const string SanitizedSasUri = "https://sanitized.blob.core.windows.net"; + public FormRecognizerRecordedTestSanitizer() + : base() + { + JsonPathSanitizers.Add("$..accessToken"); + } + public override void SanitizeHeaders(IDictionary headers) { if (headers.ContainsKey(Constants.AuthorizationHeader)) diff --git a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/CopyModelError.json b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/CopyModelError.json new file mode 100644 index 000000000000..994bdd7b7ab4 --- /dev/null +++ b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/CopyModelError.json @@ -0,0 +1,52 @@ +{ + "Entries": [ + { + "RequestUri": "https://mariari-fr-westcentralus.cognitiveservices.azure.com/formrecognizer/v2.0-preview/custom/models/00000000-0000-0000-0000-000000000000/copy", + "RequestMethod": "POST", + "RequestHeaders": { + "Content-Length": "214", + "Content-Type": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "Request-Id": "|a672d89f-4d7f0ad75e146332.", + "User-Agent": [ + "azsdk-net-AI.FormRecognizer/1.0.0-dev.20200610.1", + "(.NET Core 4.6.28516.03; Microsoft Windows 10.0.18363 )" + ], + "x-ms-client-request-id": "4a1ed720d3f4a8e2414f001be48d9102", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "targetResourceId": "resourceId", + "targetResourceRegion": "westcentralus", + "copyAuthorization": { + "modelId": "328c3b7d - a563 - 4ba2 - 8c2f - 2f26d664486a", + "accessToken": "Sanitized", + "expirationDateTimeTicks": 1591932653 + } + }, + "StatusCode": 400, + "ResponseHeaders": { + "apim-request-id": "aa8bfe6f-0d90-4545-9fb0-1cc5d9bb8c9b", + "Content-Type": "application/json; charset=utf-8", + "Date": "Thu, 11 Jun 2020 03:45:10 GMT", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "Transfer-Encoding": "chunked", + "X-Content-Type-Options": "nosniff", + "x-envoy-upstream-service-time": "6" + }, + "ResponseBody": { + "error": { + "code": "1002", + "message": "Copy request is invalid. Field \u0027TargetResourceId\u0027 must be a valid Azure Resource ID." + } + } + } + ], + "Variables": { + "FORM_RECOGNIZER_API_KEY": "Sanitized", + "FORM_RECOGNIZER_ENDPOINT": "https://mariari-fr-westcentralus.cognitiveservices.azure.com/", + "FORM_RECOGNIZER_TARGET_RESOURCE_ID": "/subscriptions/faa080af-c1d8-40ad-9cce-e1a450ca5b57/resourceGroups/mariari-group/providers/Microsoft.CognitiveServices/accounts/mariari-fr-westcentralus", + "FORM_RECOGNIZER_TARGET_RESOURCE_REGION": "westcentralus", + "RandomSeed": "1610020911" + } +} \ No newline at end of file diff --git a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/CopyModelErrorAsync.json b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/CopyModelErrorAsync.json new file mode 100644 index 000000000000..3c2712dc7014 --- /dev/null +++ b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/CopyModelErrorAsync.json @@ -0,0 +1,52 @@ +{ + "Entries": [ + { + "RequestUri": "https://mariari-fr-westcentralus.cognitiveservices.azure.com/formrecognizer/v2.0-preview/custom/models/00000000-0000-0000-0000-000000000000/copy", + "RequestMethod": "POST", + "RequestHeaders": { + "Content-Length": "214", + "Content-Type": "application/json", + "Ocp-Apim-Subscription-Key": "Sanitized", + "Request-Id": "|9b81193b-4d4c6dc7d67a1495.", + "User-Agent": [ + "azsdk-net-AI.FormRecognizer/1.0.0-dev.20200610.1", + "(.NET Core 4.6.28516.03; Microsoft Windows 10.0.18363 )" + ], + "x-ms-client-request-id": "9a25eafa44fd73269c2faf1985a3defc", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": { + "targetResourceId": "resourceId", + "targetResourceRegion": "westcentralus", + "copyAuthorization": { + "modelId": "328c3b7d - a563 - 4ba2 - 8c2f - 2f26d664486a", + "accessToken": "Sanitized", + "expirationDateTimeTicks": 1591932653 + } + }, + "StatusCode": 400, + "ResponseHeaders": { + "apim-request-id": "a09ecd33-ab21-4a30-9947-73a462b88d74", + "Content-Type": "application/json; charset=utf-8", + "Date": "Thu, 11 Jun 2020 03:45:54 GMT", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "Transfer-Encoding": "chunked", + "X-Content-Type-Options": "nosniff", + "x-envoy-upstream-service-time": "2" + }, + "ResponseBody": { + "error": { + "code": "1002", + "message": "Copy request is invalid. Field \u0027TargetResourceId\u0027 must be a valid Azure Resource ID." + } + } + } + ], + "Variables": { + "FORM_RECOGNIZER_API_KEY": "Sanitized", + "FORM_RECOGNIZER_ENDPOINT": "https://mariari-fr-westcentralus.cognitiveservices.azure.com/", + "FORM_RECOGNIZER_TARGET_RESOURCE_ID": "/subscriptions/faa080af-c1d8-40ad-9cce-e1a450ca5b57/resourceGroups/mariari-group/providers/Microsoft.CognitiveServices/accounts/mariari-fr-westcentralus", + "FORM_RECOGNIZER_TARGET_RESOURCE_REGION": "westcentralus", + "RandomSeed": "1135186625" + } +} \ No newline at end of file diff --git a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/GetCopyAuthorization.json b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/GetCopyAuthorization.json new file mode 100644 index 000000000000..5768adb4606a --- /dev/null +++ b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/GetCopyAuthorization.json @@ -0,0 +1,42 @@ +{ + "Entries": [ + { + "RequestUri": "https://mariari-fr-westcentralus.cognitiveservices.azure.com/formrecognizer/v2.0-preview/custom/models/copyAuthorization", + "RequestMethod": "POST", + "RequestHeaders": { + "Ocp-Apim-Subscription-Key": "Sanitized", + "Request-Id": "|958997bb-46928b3ddd6feb56.", + "User-Agent": [ + "azsdk-net-AI.FormRecognizer/1.0.0-dev.20200610.1", + "(.NET Core 4.6.28516.03; Microsoft Windows 10.0.18363 )" + ], + "x-ms-client-request-id": "3c60dfe489b39a2ef76b49a6fa3f9c7e", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": null, + "StatusCode": 201, + "ResponseHeaders": { + "apim-request-id": "7ca4a302-9dc5-4afe-9228-27b2204e7029", + "Content-Type": "application/json; charset=utf-8", + "Date": "Thu, 11 Jun 2020 03:37:30 GMT", + "Location": "https://mariari-fr-westcentralus.cognitiveservices.azure.com/formrecognizer/v2.0-preview/custom/models/49b81f20-9800-4b91-af49-b0612266451e", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "Transfer-Encoding": "chunked", + "X-Content-Type-Options": "nosniff", + "x-envoy-upstream-service-time": "182" + }, + "ResponseBody": { + "modelId": "49b81f20-9800-4b91-af49-b0612266451e", + "accessToken": "Sanitized", + "expirationDateTimeTicks": 1591933051 + } + } + ], + "Variables": { + "FORM_RECOGNIZER_API_KEY": "Sanitized", + "FORM_RECOGNIZER_ENDPOINT": "https://mariari-fr-westcentralus.cognitiveservices.azure.com/", + "FORM_RECOGNIZER_TARGET_RESOURCE_ID": "/subscriptions/faa080af-c1d8-40ad-9cce-e1a450ca5b57/resourceGroups/mariari-group/providers/Microsoft.CognitiveServices/accounts/mariari-fr-westcentralus", + "FORM_RECOGNIZER_TARGET_RESOURCE_REGION": "westcentralus", + "RandomSeed": "519747628" + } +} \ No newline at end of file diff --git a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/GetCopyAuthorizationAsync.json b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/GetCopyAuthorizationAsync.json new file mode 100644 index 000000000000..973c08d30898 --- /dev/null +++ b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/GetCopyAuthorizationAsync.json @@ -0,0 +1,42 @@ +{ + "Entries": [ + { + "RequestUri": "https://mariari-fr-westcentralus.cognitiveservices.azure.com/formrecognizer/v2.0-preview/custom/models/copyAuthorization", + "RequestMethod": "POST", + "RequestHeaders": { + "Ocp-Apim-Subscription-Key": "Sanitized", + "Request-Id": "|6b0c2ffe-47d2a71d763e5039.", + "User-Agent": [ + "azsdk-net-AI.FormRecognizer/1.0.0-dev.20200610.1", + "(.NET Core 4.6.28516.03; Microsoft Windows 10.0.18363 )" + ], + "x-ms-client-request-id": "5b3205118e066e0a6fa56886587149e7", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": null, + "StatusCode": 201, + "ResponseHeaders": { + "apim-request-id": "393a3e2e-57f6-4f0b-90f4-c31da1df2a00", + "Content-Type": "application/json; charset=utf-8", + "Date": "Thu, 11 Jun 2020 03:46:15 GMT", + "Location": "https://mariari-fr-westcentralus.cognitiveservices.azure.com/formrecognizer/v2.0-preview/custom/models/dd25821b-cc46-4f28-97da-127615ff1905", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "Transfer-Encoding": "chunked", + "X-Content-Type-Options": "nosniff", + "x-envoy-upstream-service-time": "310" + }, + "ResponseBody": { + "modelId": "dd25821b-cc46-4f28-97da-127615ff1905", + "accessToken": "Sanitized", + "expirationDateTimeTicks": 1591933575 + } + } + ], + "Variables": { + "FORM_RECOGNIZER_API_KEY": "Sanitized", + "FORM_RECOGNIZER_ENDPOINT": "https://mariari-fr-westcentralus.cognitiveservices.azure.com/", + "FORM_RECOGNIZER_TARGET_RESOURCE_ID": "/subscriptions/faa080af-c1d8-40ad-9cce-e1a450ca5b57/resourceGroups/mariari-group/providers/Microsoft.CognitiveServices/accounts/mariari-fr-westcentralus", + "FORM_RECOGNIZER_TARGET_RESOURCE_REGION": "westcentralus", + "RandomSeed": "443274679" + } +} \ No newline at end of file diff --git a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/SerializeDeserializeCopyAuthorizationAsync.json b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/SerializeDeserializeCopyAuthorizationAsync.json new file mode 100644 index 000000000000..ff62cfe7bda3 --- /dev/null +++ b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/SerializeDeserializeCopyAuthorizationAsync.json @@ -0,0 +1,42 @@ +{ + "Entries": [ + { + "RequestUri": "https://mariari-fr-westcentralus.cognitiveservices.azure.com/formrecognizer/v2.0-preview/custom/models/copyAuthorization", + "RequestMethod": "POST", + "RequestHeaders": { + "Ocp-Apim-Subscription-Key": "Sanitized", + "Request-Id": "|958997bc-46928b3ddd6feb56.", + "User-Agent": [ + "azsdk-net-AI.FormRecognizer/1.0.0-dev.20200610.1", + "(.NET Core 4.6.28516.03; Microsoft Windows 10.0.18363 )" + ], + "x-ms-client-request-id": "0a1cbda37f9e70a8a42c8e33c9482589", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": null, + "StatusCode": 201, + "ResponseHeaders": { + "apim-request-id": "37940ccc-9669-4d7f-b12f-61595f4f6efc", + "Content-Type": "application/json; charset=utf-8", + "Date": "Thu, 11 Jun 2020 03:37:31 GMT", + "Location": "https://mariari-fr-westcentralus.cognitiveservices.azure.com/formrecognizer/v2.0-preview/custom/models/76ad485a-9e50-4aa8-81f1-22a2e5eaf955", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "Transfer-Encoding": "chunked", + "X-Content-Type-Options": "nosniff", + "x-envoy-upstream-service-time": "90" + }, + "ResponseBody": { + "modelId": "76ad485a-9e50-4aa8-81f1-22a2e5eaf955", + "accessToken": "Sanitized", + "expirationDateTimeTicks": 1591933051 + } + } + ], + "Variables": { + "FORM_RECOGNIZER_API_KEY": "Sanitized", + "FORM_RECOGNIZER_ENDPOINT": "https://mariari-fr-westcentralus.cognitiveservices.azure.com/", + "FORM_RECOGNIZER_TARGET_RESOURCE_ID": "/subscriptions/faa080af-c1d8-40ad-9cce-e1a450ca5b57/resourceGroups/mariari-group/providers/Microsoft.CognitiveServices/accounts/mariari-fr-westcentralus", + "FORM_RECOGNIZER_TARGET_RESOURCE_REGION": "westcentralus", + "RandomSeed": "825959497" + } +} \ No newline at end of file diff --git a/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/SerializeDeserializeCopyAuthorizationAsyncAsync.json b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/SerializeDeserializeCopyAuthorizationAsyncAsync.json new file mode 100644 index 000000000000..5dcfa90c7a2e --- /dev/null +++ b/sdk/formrecognizer/Azure.AI.FormRecognizer/tests/SessionRecords/FormTrainingClientLiveTests/SerializeDeserializeCopyAuthorizationAsyncAsync.json @@ -0,0 +1,42 @@ +{ + "Entries": [ + { + "RequestUri": "https://mariari-fr-westcentralus.cognitiveservices.azure.com/formrecognizer/v2.0-preview/custom/models/copyAuthorization", + "RequestMethod": "POST", + "RequestHeaders": { + "Ocp-Apim-Subscription-Key": "Sanitized", + "Request-Id": "|958997bf-46928b3ddd6feb56.", + "User-Agent": [ + "azsdk-net-AI.FormRecognizer/1.0.0-dev.20200610.1", + "(.NET Core 4.6.28516.03; Microsoft Windows 10.0.18363 )" + ], + "x-ms-client-request-id": "6b032b4a9426b0ab38894827f47f90c1", + "x-ms-return-client-request-id": "true" + }, + "RequestBody": null, + "StatusCode": 201, + "ResponseHeaders": { + "apim-request-id": "c1e4ada6-cc7c-4fcc-91be-053baaa5221f", + "Content-Type": "application/json; charset=utf-8", + "Date": "Thu, 11 Jun 2020 03:37:31 GMT", + "Location": "https://mariari-fr-westcentralus.cognitiveservices.azure.com/formrecognizer/v2.0-preview/custom/models/f6a9c0d5-f411-4555-91ef-d5e3a117de55", + "Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload", + "Transfer-Encoding": "chunked", + "X-Content-Type-Options": "nosniff", + "x-envoy-upstream-service-time": "93" + }, + "ResponseBody": { + "modelId": "f6a9c0d5-f411-4555-91ef-d5e3a117de55", + "accessToken": "Sanitized", + "expirationDateTimeTicks": 1591933052 + } + } + ], + "Variables": { + "FORM_RECOGNIZER_API_KEY": "Sanitized", + "FORM_RECOGNIZER_ENDPOINT": "https://mariari-fr-westcentralus.cognitiveservices.azure.com/", + "FORM_RECOGNIZER_TARGET_RESOURCE_ID": "/subscriptions/faa080af-c1d8-40ad-9cce-e1a450ca5b57/resourceGroups/mariari-group/providers/Microsoft.CognitiveServices/accounts/mariari-fr-westcentralus", + "FORM_RECOGNIZER_TARGET_RESOURCE_REGION": "westcentralus", + "RandomSeed": "932612069" + } +} \ No newline at end of file From 01cb4d6bbecea22e0936e86d5fc93d3766d69db6 Mon Sep 17 00:00:00 2001 From: Mariana Rios Flores Date: Thu, 11 Jun 2020 21:27:13 -0700 Subject: [PATCH 2/4] PR feedback --- doc/dev/Track2TestFramework.md | 15 ++++++-- .../src/RecordedTestSanitizer.cs | 34 ++++++++++--------- .../Azure.Core/tests/RecordSessionTests.cs | 29 ++++++++++++++++ 3 files changed, 59 insertions(+), 19 deletions(-) diff --git a/doc/dev/Track2TestFramework.md b/doc/dev/Track2TestFramework.md index 733bcd6c709b..6bc7afd94d8f 100644 --- a/doc/dev/Track2TestFramework.md +++ b/doc/dev/Track2TestFramework.md @@ -1,17 +1,18 @@ # Acquiring TestFramework -To start using test framework import `sdk\core\Azure.Core\tests\TestFramework.props` into test `.csproj`: +To start using Test Framework add a project reference using the alias `AzureCoreTestFramework` into your test `.csproj`: ``` xml ... - + ... ``` +As an example, see the [Template](https://github.com/Azure/azure-sdk-for-net/blob/b9bd85cb2591f7c3f3c054f33f158e758056f1d3/sdk/template/Azure.Template/tests/Azure.Template.Tests.csproj#L15) project. # Sync-async tests @@ -182,13 +183,19 @@ __NOTE:__ recordings are copied from `netcoreapp2.1` directory by default, make ## Sanitizing -Secrets that are part of requests, responses, headers or connections strings should be sanitized before saving the record. Common headers like `Authentication` are sanitized automatically but if custom logic is required `RecordedTest.Sanitizer` should be used as extension point. +Secrets that are part of requests, responses, headers, or connections strings should be sanitized before saving the record. Common headers like `Authentication` are sanitized automatically but if custom logic is required and/or if request or response body need to be sanitied, the `RecordedTest.Sanitizer` should be used as extension point. For example: ``` C# public class ConfigurationRecordedTestSanitizer : RecordedTestSanitizer { + public ConfigurationRecordedTestSanitizer() + base() + { + JsonPathSanitizers.Add("$..secret"); + } + public override void SanitizeConnectionString(ConnectionString connectionString) { const string secretKey = "secret"; @@ -209,6 +216,8 @@ For example: } ``` +**Note:** `JsonPathSanitizers` takes [Json Path](https://www.newtonsoft.com/json/help/html/QueryJsonSelectToken.htm) format strings that will be validated against the body. If a match exists, the value will be sanitized. + ## Matching When tests are ran in replay mode HTTP method, uri and headers are used to match request to response. Some headers change on every request and are not controlled by the client code and should be ignored during the matching. Common headers like `Date`, `x-ms-date`, `x-ms-client-request-id`, `User-Agent`, `Request-Id` are ignored by default but if more headers need to be ignored use `Recording.Matcher` extensions point. diff --git a/sdk/core/Azure.Core.TestFramework/src/RecordedTestSanitizer.cs b/sdk/core/Azure.Core.TestFramework/src/RecordedTestSanitizer.cs index b147eaf8ea17..0e3cb4609078 100644 --- a/sdk/core/Azure.Core.TestFramework/src/RecordedTestSanitizer.cs +++ b/sdk/core/Azure.Core.TestFramework/src/RecordedTestSanitizer.cs @@ -13,7 +13,8 @@ namespace Azure.Core.TestFramework public class RecordedTestSanitizer { public const string SanitizeValue = "Sanitized"; - public static List JsonPathSanitizers = new List(); + public List JsonPathSanitizers { get; } = new List(); + private static readonly string[] s_sanitizeValueArray = { SanitizeValue }; private static readonly string[] s_sanitizedHeaders = { "Authorization" }; @@ -36,12 +37,24 @@ public virtual void SanitizeHeaders(IDictionary headers) public virtual string SanitizeTextBody(string contentType, string body) { - foreach (var jsonPath in JsonPathSanitizers) + if (JsonPathSanitizers.Count == 0) + return body; + try { - return SanitizeJsonBody(body, jsonPath); + var jsonO = JObject.Parse(body); + foreach (var jsonPath in JsonPathSanitizers) + { + foreach (JToken token in jsonO.SelectTokens(jsonPath)) + { + token.Replace(JToken.FromObject(SanitizeValue)); + } + } + return JsonConvert.SerializeObject(jsonO); + } + catch + { + return body; } - - return body; } public virtual byte[] SanitizeBody(string contentType, byte[] body) @@ -49,17 +62,6 @@ public virtual byte[] SanitizeBody(string contentType, byte[] body) return body; } - public virtual string SanitizeJsonBody(string body, string jsonPath) - { - var jsonO = JObject.Parse(body); - - foreach (JToken token in jsonO.SelectTokens(jsonPath)) - { - token.Replace(JToken.FromObject(SanitizeValue)); - } - return JsonConvert.SerializeObject(jsonO); - } - public virtual string SanitizeVariable(string variableName, string environmentVariableValue) => environmentVariableValue; public virtual void SanitizeBody(RecordEntryMessage message) diff --git a/sdk/core/Azure.Core/tests/RecordSessionTests.cs b/sdk/core/Azure.Core/tests/RecordSessionTests.cs index 197a95b8c8da..b137d90e289e 100644 --- a/sdk/core/Azure.Core/tests/RecordSessionTests.cs +++ b/sdk/core/Azure.Core/tests/RecordSessionTests.cs @@ -206,6 +206,35 @@ public void RecordingSessionSanitizeSanitizesVariables() Assert.AreEqual("Totally not a SANITIZED", session.Variables["B"]); } + [TestCase("*", "invalid json", "invalid json")] + [TestCase("$..secret", + "{\"secret\":\"I should be sanitized\",\"level\":{\"key\":\"value\",\"secret\":\"I should be sanitized\"}}", + "{\"secret\":\"Sanitized\",\"level\":{\"key\":\"value\",\"secret\":\"Sanitized\"}}")] + public void RecordingSessionSanitizeTextBody(string jsonPath, string body, string expected) + { + var sanitizer = new RecordedTestSanitizer(); + sanitizer.JsonPathSanitizers.Add(jsonPath); + + string response = sanitizer.SanitizeTextBody(default, body); + + Assert.AreEqual(expected, response); + } + + [Test] + public void RecordingSessionSanitizeTextBodyMultipleValues() + { + var sanitizer = new RecordedTestSanitizer(); + sanitizer.JsonPathSanitizers.Add("$..secret"); + sanitizer.JsonPathSanitizers.Add("$..topSecret"); + + var body = "{\"secret\":\"I should be sanitized\",\"key\":\"value\",\"topSecret\":\"I should be sanitized\"}"; + var expected = "{\"secret\":\"Sanitized\",\"key\":\"value\",\"topSecret\":\"Sanitized\"}"; + + string response = sanitizer.SanitizeTextBody(default, body); + + Assert.AreEqual(expected, response); + } + [Test] public void SavingRecordingSanitizesValues() { From 1ca33798934005fbc749ac5ef53482820a23a915 Mon Sep 17 00:00:00 2001 From: Mariana Rios Flores Date: Thu, 11 Jun 2020 21:32:13 -0700 Subject: [PATCH 3/4] update to master --- doc/dev/Track2TestFramework.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/dev/Track2TestFramework.md b/doc/dev/Track2TestFramework.md index 6bc7afd94d8f..940f3a8ec84d 100644 --- a/doc/dev/Track2TestFramework.md +++ b/doc/dev/Track2TestFramework.md @@ -12,7 +12,7 @@ To start using Test Framework add a project reference using the alias `AzureCore ``` -As an example, see the [Template](https://github.com/Azure/azure-sdk-for-net/blob/b9bd85cb2591f7c3f3c054f33f158e758056f1d3/sdk/template/Azure.Template/tests/Azure.Template.Tests.csproj#L15) project. +As an example, see the [Template](https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/template/Azure.Template/tests/Azure.Template.Tests.csproj#L15) project. # Sync-async tests From a6e2cd5c60694e6bcc5589c3ac4b32b103dc0da4 Mon Sep 17 00:00:00 2001 From: Mariana Rios Flores Date: Sat, 13 Jun 2020 10:16:10 -0700 Subject: [PATCH 4/4] no var --- sdk/core/Azure.Core.TestFramework/src/RecordedTestSanitizer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/core/Azure.Core.TestFramework/src/RecordedTestSanitizer.cs b/sdk/core/Azure.Core.TestFramework/src/RecordedTestSanitizer.cs index 0e3cb4609078..bc7d01afcc29 100644 --- a/sdk/core/Azure.Core.TestFramework/src/RecordedTestSanitizer.cs +++ b/sdk/core/Azure.Core.TestFramework/src/RecordedTestSanitizer.cs @@ -42,7 +42,7 @@ public virtual string SanitizeTextBody(string contentType, string body) try { var jsonO = JObject.Parse(body); - foreach (var jsonPath in JsonPathSanitizers) + foreach (string jsonPath in JsonPathSanitizers) { foreach (JToken token in jsonO.SelectTokens(jsonPath)) {