From 0559930e09e4d89b621701a73abcc12d4b514fda Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Thu, 29 Jun 2023 23:42:51 +0800 Subject: [PATCH 01/21] Support Azure.Maps.Search to authenticate with SAS token --- sdk/maps/Azure.Maps.Common/CHANGELOG.md | 6 +--- .../api/Azure.Maps.Common.netstandard2.0.cs | 5 +++ .../src/MapsSasCredentialPolicy.cs | 33 +++++++++++++++++++ .../tests/MapsSasCredentialPolicyTests.cs | 25 ++++++++++++++ sdk/maps/Azure.Maps.Search/CHANGELOG.md | 2 ++ sdk/maps/Azure.Maps.Search/README.md | 12 +++++++ .../api/Azure.Maps.Search.netstandard2.0.cs | 2 ++ .../Azure.Maps.Search/src/MapsSearchClient.cs | 32 +++++++++++++++++- .../tests/Samples/SearchClientSamples.cs | 10 ++++++ 9 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 sdk/maps/Azure.Maps.Common/src/MapsSasCredentialPolicy.cs create mode 100644 sdk/maps/Azure.Maps.Common/tests/MapsSasCredentialPolicyTests.cs diff --git a/sdk/maps/Azure.Maps.Common/CHANGELOG.md b/sdk/maps/Azure.Maps.Common/CHANGELOG.md index bee98ee7fbd0c..2983faa1f2945 100644 --- a/sdk/maps/Azure.Maps.Common/CHANGELOG.md +++ b/sdk/maps/Azure.Maps.Common/CHANGELOG.md @@ -4,11 +4,7 @@ ### Features Added -### Breaking Changes - -### Bugs Fixed - -### Other Changes +- Create SAS credential policy ## 1.0.0-beta.3 (2022-11-08) diff --git a/sdk/maps/Azure.Maps.Common/api/Azure.Maps.Common.netstandard2.0.cs b/sdk/maps/Azure.Maps.Common/api/Azure.Maps.Common.netstandard2.0.cs index ed44597cbf784..19f5041538b1a 100644 --- a/sdk/maps/Azure.Maps.Common/api/Azure.Maps.Common.netstandard2.0.cs +++ b/sdk/maps/Azure.Maps.Common/api/Azure.Maps.Common.netstandard2.0.cs @@ -34,4 +34,9 @@ namespace Azure.Maps public static bool operator !=(Azure.Maps.LocalizedMapView left, Azure.Maps.LocalizedMapView right) { throw null; } public override string ToString() { throw null; } } + public partial class MapsSasCredentialPolicy : Azure.Core.Pipeline.HttpPipelineSynchronousPolicy + { + public MapsSasCredentialPolicy(Azure.AzureSasCredential credential) { } + public override void OnSendingRequest(Azure.Core.HttpMessage message) { } + } } diff --git a/sdk/maps/Azure.Maps.Common/src/MapsSasCredentialPolicy.cs b/sdk/maps/Azure.Maps.Common/src/MapsSasCredentialPolicy.cs new file mode 100644 index 0000000000000..0170ab93678e8 --- /dev/null +++ b/sdk/maps/Azure.Maps.Common/src/MapsSasCredentialPolicy.cs @@ -0,0 +1,33 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Azure.Core; +using Azure.Core.Pipeline; + +namespace Azure.Maps +{ + /// The MapsSasCredentialPolicy used for SAS authentication. + public class MapsSasCredentialPolicy : HttpPipelineSynchronousPolicy + { + private readonly string _sasAuthenticationHeader = "Authorization"; + private readonly string _sasPrefix = "jwt-sas"; + private readonly AzureSasCredential _credential; + + /// + /// Initializes a new instance of the class. + /// + /// The used to authenticate requests. + public MapsSasCredentialPolicy(AzureSasCredential credential) + { + Argument.AssertNotNull(credential, nameof(credential)); + _credential = credential; + } + + /// + public override void OnSendingRequest(HttpMessage message) + { + base.OnSendingRequest(message); + message.Request.Headers.SetValue(_sasAuthenticationHeader, _sasPrefix + " " + _credential.Signature); + } + } +} diff --git a/sdk/maps/Azure.Maps.Common/tests/MapsSasCredentialPolicyTests.cs b/sdk/maps/Azure.Maps.Common/tests/MapsSasCredentialPolicyTests.cs new file mode 100644 index 0000000000000..6353ac2bb4e30 --- /dev/null +++ b/sdk/maps/Azure.Maps.Common/tests/MapsSasCredentialPolicyTests.cs @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Azure.Maps; +using Azure.Core.TestFramework; +using NUnit.Framework; + +namespace Azure.Maps.Tests +{ + public class MapsSasCredentialPolicyTests + { + [Test] + public void MapsSasCredentialPolicyTest() + { + // Exception case + Assert.Throws(() => new MapsSasCredentialPolicy(null)); + + // Normal case + var credentialPolicy = new MapsSasCredentialPolicy(new AzureSasCredential("Sas Token")); + + Assert.NotNull(credentialPolicy); + } + } +} diff --git a/sdk/maps/Azure.Maps.Search/CHANGELOG.md b/sdk/maps/Azure.Maps.Search/CHANGELOG.md index 714dbdc31437a..dfe0d611a442f 100644 --- a/sdk/maps/Azure.Maps.Search/CHANGELOG.md +++ b/sdk/maps/Azure.Maps.Search/CHANGELOG.md @@ -4,6 +4,8 @@ ### Features Added +- Support SAS authentication + ### Breaking Changes ### Bugs Fixed diff --git a/sdk/maps/Azure.Maps.Search/README.md b/sdk/maps/Azure.Maps.Search/README.md index c0bcfc0cfef4e..1d82c59ae9497 100644 --- a/sdk/maps/Azure.Maps.Search/README.md +++ b/sdk/maps/Azure.Maps.Search/README.md @@ -54,6 +54,18 @@ string clientId = ""; MapsSearchClient client = new MapsSearchClient(credential, clientId); ``` +#### Shared Access Signature (SAS) Authentication + +Shared access signature (SAS) tokens are authentication tokens created using the JSON Web token (JWT) format and are cryptographically signed to prove authentication for an application to the Azure Maps REST API. + +To use SAS token authentication, get a SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it in `MapsSearchClient`: + +```C# Snippet:InstantiateSearchClientViaSas +// Create a SearchClient that will authenticate through SAS token +AzureSasCredential sasCredential = new AzureSasCredential(""); +MapsSearchClient client = new MapsSearchClient(sasCredential); +``` + ## Key concepts `MapsSearchClient` is designed to: diff --git a/sdk/maps/Azure.Maps.Search/api/Azure.Maps.Search.netstandard2.0.cs b/sdk/maps/Azure.Maps.Search/api/Azure.Maps.Search.netstandard2.0.cs index 1420b60ef24e4..5d9ab96e32380 100644 --- a/sdk/maps/Azure.Maps.Search/api/Azure.Maps.Search.netstandard2.0.cs +++ b/sdk/maps/Azure.Maps.Search/api/Azure.Maps.Search.netstandard2.0.cs @@ -84,6 +84,8 @@ public partial class MapsSearchClient protected MapsSearchClient() { } public MapsSearchClient(Azure.AzureKeyCredential credential) { } public MapsSearchClient(Azure.AzureKeyCredential credential, Azure.Maps.Search.MapsSearchClientOptions options) { } + public MapsSearchClient(Azure.AzureSasCredential credential) { } + public MapsSearchClient(Azure.AzureSasCredential credential, Azure.Maps.Search.MapsSearchClientOptions options) { } public MapsSearchClient(Azure.Core.TokenCredential credential, string clientId) { } public MapsSearchClient(Azure.Core.TokenCredential credential, string clientId, Azure.Maps.Search.MapsSearchClientOptions options) { } public virtual Azure.Maps.Search.FuzzySearchBatchOperation FuzzyBatchSearch(Azure.WaitUntil waitUntil, System.Collections.Generic.IEnumerable queries, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } diff --git a/sdk/maps/Azure.Maps.Search/src/MapsSearchClient.cs b/sdk/maps/Azure.Maps.Search/src/MapsSearchClient.cs index 40b735a5d5288..92f528876556a 100644 --- a/sdk/maps/Azure.Maps.Search/src/MapsSearchClient.cs +++ b/sdk/maps/Azure.Maps.Search/src/MapsSearchClient.cs @@ -9,9 +9,10 @@ using System.Threading; using System.Threading.Tasks; using Azure.Core; +using Azure.Core.GeoJson; using Azure.Core.Pipeline; +using Azure.Maps; using Azure.Maps.Search.Models; -using Azure.Core.GeoJson; namespace Azure.Maps.Search { @@ -93,6 +94,35 @@ public MapsSearchClient(TokenCredential credential, string clientId, MapsSearchC RestClient = new SearchRestClient(_clientDiagnostics, _pipeline, endpoint, clientId, options.Version); } + /// Initializes a new instance of MapsSearchClient. + /// The Shared Access Signature credential used to connect to Azure. This signature + /// can be constructed using the . + public MapsSearchClient(AzureSasCredential credential) + { + Argument.AssertNotNull(credential, nameof(credential)); + + var endpoint = new Uri("https://atlas.microsoft.com"); + var options = new MapsSearchClientOptions(); + _clientDiagnostics = new ClientDiagnostics(options); + _pipeline = HttpPipelineBuilder.Build(options, new MapsSasCredentialPolicy(credential)); + RestClient = new SearchRestClient(_clientDiagnostics, _pipeline, endpoint, null, options.Version); + } + + /// Initializes a new instance of MapsSearchClient. + /// The Shared Access Signature credential used to connect to Azure. This signature + /// can be constructed using the . + /// The options for configuring the client. + public MapsSearchClient(AzureSasCredential credential, MapsSearchClientOptions options) + { + Argument.AssertNotNull(credential, nameof(credential)); + + var endpoint = options.Endpoint; + options ??= new MapsSearchClientOptions(); + _clientDiagnostics = new ClientDiagnostics(options); + _pipeline = HttpPipelineBuilder.Build(options, new MapsSasCredentialPolicy(credential)); + RestClient = new SearchRestClient(_clientDiagnostics, _pipeline, endpoint, null, options.Version); + } + /// /// The Get Polygon service allows you to request the geometry data such as a city or country outline for a set of entities, previously retrieved from an Online Search request in GeoJSON format. The geometry ID is returned in the sourceGeometry object under "geometry" and "id" in either a Search Address or Search Fuzzy call. /// diff --git a/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs b/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs index 10a9ed34352e5..387d1a8c673d3 100644 --- a/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs +++ b/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs @@ -6,6 +6,7 @@ using System.Threading; using System.Threading.Tasks; #region Snippet:SearchImportNamespace +using Azure.Core; using Azure.Core.GeoJson; using Azure.Maps.Search; using Azure.Maps.Search.Models; @@ -37,6 +38,15 @@ public void SearchClientViaAAD() #endregion } + public void SearchClientViaSas() + { + #region Snippet:InstantiateSearchClientViaSas + // Create a SearchClient that will authenticate through SAS token + AzureSasCredential sasCredential = new AzureSasCredential(""); + MapsSearchClient client = new MapsSearchClient(sasCredential); + #endregion + } + [Test] public async Task GetPolygons() { From 06862858342220d48f916ee9b9bd964689b36766 Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Thu, 29 Jun 2023 23:44:11 +0800 Subject: [PATCH 02/21] Remove unused sections in changelog --- sdk/maps/Azure.Maps.Search/CHANGELOG.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sdk/maps/Azure.Maps.Search/CHANGELOG.md b/sdk/maps/Azure.Maps.Search/CHANGELOG.md index dfe0d611a442f..da7540840f391 100644 --- a/sdk/maps/Azure.Maps.Search/CHANGELOG.md +++ b/sdk/maps/Azure.Maps.Search/CHANGELOG.md @@ -6,12 +6,6 @@ - Support SAS authentication -### Breaking Changes - -### Bugs Fixed - -### Other Changes - ## 1.0.0-beta.3 (2022-11-08) ### Bugs Fixed From 027ebdc4ae187145d9abcfa127398f684f751f9e Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Fri, 30 Jun 2023 00:05:29 +0800 Subject: [PATCH 03/21] Fix unit test cases --- .../Azure.Maps.Search/tests/Samples/SearchClientSamples.cs | 1 - sdk/maps/Azure.Maps.Search/tests/SearchAddressTests.cs | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs b/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs index 387d1a8c673d3..65da1886b773d 100644 --- a/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs +++ b/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs @@ -6,7 +6,6 @@ using System.Threading; using System.Threading.Tasks; #region Snippet:SearchImportNamespace -using Azure.Core; using Azure.Core.GeoJson; using Azure.Maps.Search; using Azure.Maps.Search.Models; diff --git a/sdk/maps/Azure.Maps.Search/tests/SearchAddressTests.cs b/sdk/maps/Azure.Maps.Search/tests/SearchAddressTests.cs index 7bb8ef1738d09..b341f6e7d3c0f 100644 --- a/sdk/maps/Azure.Maps.Search/tests/SearchAddressTests.cs +++ b/sdk/maps/Azure.Maps.Search/tests/SearchAddressTests.cs @@ -143,7 +143,7 @@ public async Task CanSearchAddressBatch() new SearchAddressQuery("Millenium", new SearchAddressOptions { CountryFilter = new[] { "US" }}), }); - Assert.AreEqual("Redmond", searchResult.Value.Results[0].Results[0].Address.Municipality); + Assert.AreEqual("Reading", searchResult.Value.Results[0].Results[0].Address.Municipality); Assert.AreEqual("Tucson", searchResult.Value.Results[1].Results[0].Address.Municipality); } @@ -160,7 +160,7 @@ public async Task CanPollSearchAddressBatch() // delay 400 ms for the task to complete await Task.Delay(400); var searchResult = operation.WaitForCompletion(); - Assert.AreEqual("Redmond", searchResult.Value.Results[0].Results[0].Address.Municipality); + Assert.AreEqual("Reading", searchResult.Value.Results[0].Results[0].Address.Municipality); Assert.AreEqual("Tucson", searchResult.Value.Results[1].Results[0].Address.Municipality); } } From e6bb43eb76f2bd26c49430525ea595512f91dc72 Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Fri, 30 Jun 2023 09:16:13 +0800 Subject: [PATCH 04/21] Update /sdk/maps codeowners --- .github/CODEOWNERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b862aef4c6f6a..bfb3085e763b8 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -39,7 +39,7 @@ /sdk/entra/ @pallavit @jsquire /sdk/graphrbac/ @pallavit @jsquire /sdk/machinelearningservices/ @pallavit @jsquire -/sdk/maps/ @pallavit @jsquire +/sdk/maps/ @pallavit @jsquire @dubiety @khmic5 @andykao1213 # Note there are some sub-rules for this directory, defined below /sdk/operationalinsights/ @pallavit @jsquire /sdk/purview/ @pallavit @jsquire From d7dd1eec8b3b870f66f1232e71439767b79d35dd Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Fri, 30 Jun 2023 09:42:24 +0800 Subject: [PATCH 05/21] Update unit test cases --- sdk/maps/Azure.Maps.Search/tests/SearchAddressTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/maps/Azure.Maps.Search/tests/SearchAddressTests.cs b/sdk/maps/Azure.Maps.Search/tests/SearchAddressTests.cs index b341f6e7d3c0f..7bb8ef1738d09 100644 --- a/sdk/maps/Azure.Maps.Search/tests/SearchAddressTests.cs +++ b/sdk/maps/Azure.Maps.Search/tests/SearchAddressTests.cs @@ -143,7 +143,7 @@ public async Task CanSearchAddressBatch() new SearchAddressQuery("Millenium", new SearchAddressOptions { CountryFilter = new[] { "US" }}), }); - Assert.AreEqual("Reading", searchResult.Value.Results[0].Results[0].Address.Municipality); + Assert.AreEqual("Redmond", searchResult.Value.Results[0].Results[0].Address.Municipality); Assert.AreEqual("Tucson", searchResult.Value.Results[1].Results[0].Address.Municipality); } @@ -160,7 +160,7 @@ public async Task CanPollSearchAddressBatch() // delay 400 ms for the task to complete await Task.Delay(400); var searchResult = operation.WaitForCompletion(); - Assert.AreEqual("Reading", searchResult.Value.Results[0].Results[0].Address.Municipality); + Assert.AreEqual("Redmond", searchResult.Value.Results[0].Results[0].Address.Municipality); Assert.AreEqual("Tucson", searchResult.Value.Results[1].Results[0].Address.Municipality); } } From 8573205894d8da13054a13dfaefc4335f6359e6e Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Fri, 30 Jun 2023 13:03:49 +0800 Subject: [PATCH 06/21] Update readme and samples --- sdk/maps/Azure.Maps.Search/README.md | 43 ++++++++++++++++++- .../samples/FuzzySearchSamples.md | 2 +- .../samples/GeoJsonSearchSamples.md | 2 +- .../samples/ReverseSearchAddressSamples.md | 2 +- .../samples/SearchAddressSamples.md | 2 +- .../tests/Azure.Maps.Search.Tests.csproj | 2 + .../tests/Samples/SearchClientSamples.cs | 26 ++++++++++- 7 files changed, 71 insertions(+), 8 deletions(-) diff --git a/sdk/maps/Azure.Maps.Search/README.md b/sdk/maps/Azure.Maps.Search/README.md index 1d82c59ae9497..b8f290279ba39 100644 --- a/sdk/maps/Azure.Maps.Search/README.md +++ b/sdk/maps/Azure.Maps.Search/README.md @@ -58,11 +58,50 @@ MapsSearchClient client = new MapsSearchClient(credential, clientId); Shared access signature (SAS) tokens are authentication tokens created using the JSON Web token (JWT) format and are cryptographically signed to prove authentication for an application to the Azure Maps REST API. -To use SAS token authentication, get a SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it in `MapsSearchClient`: +Before integratingSAS token authentication, we need to install `Azure.ResourceManager` and `Azure.ResourceManager.Maps` (version 1.1.0-beta.2 or higher): + +```powershell +dotnet add package Azure.ResourceManager +dotnet add package Azure.ResourceManager.Maps --prerelease +``` + +In the code, we need to import the following lines for both Azure Maps SDK and ResourceManager: + +```C# Snippet:SearchImportNamespaces +using Azure.Core.GeoJson; +using Azure.Maps.Search; +using Azure.Maps.Search.Models; +``` + +```C# Snippet:SasAuthImportNamespaces +using Azure.Core; +using Azure.ResourceManager; +using Azure.ResourceManager.Maps; +using Azure.ResourceManager.Maps.Models; +``` + +And then we can get SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it in `MapsSearchClient`: + ```C# Snippet:InstantiateSearchClientViaSas +// Get your azure access token, for more details of how Azure SDK get your access token, please refer to https://learn.microsoft.com/en-us/dotnet/azure/sdk/authentication?tabs=command-line +TokenCredential cred = new DefaultAzureCredential(); +// Authenticate your client +ArmClient armClient = new ArmClient(cred); + +string subscriptionId = "MyMapsSubscriptionId"; +string resourceGroupName = "MyMapsResourceGroupName"; +string accountName = "MyMapsAccountName"; +ResourceIdentifier mapsAccountResourceId = MapsAccountResource.CreateResourceIdentifier(subscriptionId, resourceGroupName, accountName); +MapsAccountResource mapsAccount = armClient.GetMapsAccountResource(mapsAccountResourceId); + +var principalId = "MyManagedIdentityObjectId"; +int maxRatePerSecond = 500; +var sasContent = new MapsAccountSasContent(MapsSigningKey.PrimaryKey, principalId, maxRatePerSecond, "2023-06-30T04:27:28.734Z", "2023-06-30T12:27:28.734Z"); +var sas = mapsAccount.GetSas(sasContent); + // Create a SearchClient that will authenticate through SAS token -AzureSasCredential sasCredential = new AzureSasCredential(""); +AzureSasCredential sasCredential = new AzureSasCredential(sas.Value.AccountSasToken); MapsSearchClient client = new MapsSearchClient(sasCredential); ``` diff --git a/sdk/maps/Azure.Maps.Search/samples/FuzzySearchSamples.md b/sdk/maps/Azure.Maps.Search/samples/FuzzySearchSamples.md index d3be796c1e52b..5c36f6a25ea30 100644 --- a/sdk/maps/Azure.Maps.Search/samples/FuzzySearchSamples.md +++ b/sdk/maps/Azure.Maps.Search/samples/FuzzySearchSamples.md @@ -4,7 +4,7 @@ To use these samples, you'll first need to set up resources. See [getting starte ## Import the namespaces -```C# Snippet:SearchImportNamespace +```C# Snippet:SearchImportNamespaces using Azure.Core.GeoJson; using Azure.Maps.Search; using Azure.Maps.Search.Models; diff --git a/sdk/maps/Azure.Maps.Search/samples/GeoJsonSearchSamples.md b/sdk/maps/Azure.Maps.Search/samples/GeoJsonSearchSamples.md index f44284ed77d5c..90489d094229e 100644 --- a/sdk/maps/Azure.Maps.Search/samples/GeoJsonSearchSamples.md +++ b/sdk/maps/Azure.Maps.Search/samples/GeoJsonSearchSamples.md @@ -4,7 +4,7 @@ To use these samples, you'll first need to set up resources. See [getting starte ## Import the namespaces -```C# Snippet:SearchImportNamespace +```C# Snippet:SearchImportNamespaces using Azure.Core.GeoJson; using Azure.Maps.Search; using Azure.Maps.Search.Models; diff --git a/sdk/maps/Azure.Maps.Search/samples/ReverseSearchAddressSamples.md b/sdk/maps/Azure.Maps.Search/samples/ReverseSearchAddressSamples.md index 367b3eb2aa7da..a74fbd2f51aef 100644 --- a/sdk/maps/Azure.Maps.Search/samples/ReverseSearchAddressSamples.md +++ b/sdk/maps/Azure.Maps.Search/samples/ReverseSearchAddressSamples.md @@ -4,7 +4,7 @@ To use these samples, you'll first need to set up resources. See [getting starte ## Import the namespaces -```C# Snippet:SearchImportNamespace +```C# Snippet:SearchImportNamespaces using Azure.Core.GeoJson; using Azure.Maps.Search; using Azure.Maps.Search.Models; diff --git a/sdk/maps/Azure.Maps.Search/samples/SearchAddressSamples.md b/sdk/maps/Azure.Maps.Search/samples/SearchAddressSamples.md index cc18ec426798f..b0930bc150967 100644 --- a/sdk/maps/Azure.Maps.Search/samples/SearchAddressSamples.md +++ b/sdk/maps/Azure.Maps.Search/samples/SearchAddressSamples.md @@ -4,7 +4,7 @@ To use these samples, you'll first need to set up resources. See [getting starte ## Import the namespaces -```C# Snippet:SearchImportNamespace +```C# Snippet:SearchImportNamespaces using Azure.Core.GeoJson; using Azure.Maps.Search; using Azure.Maps.Search.Models; diff --git a/sdk/maps/Azure.Maps.Search/tests/Azure.Maps.Search.Tests.csproj b/sdk/maps/Azure.Maps.Search/tests/Azure.Maps.Search.Tests.csproj index ea4784552061e..27d290acec7ac 100644 --- a/sdk/maps/Azure.Maps.Search/tests/Azure.Maps.Search.Tests.csproj +++ b/sdk/maps/Azure.Maps.Search/tests/Azure.Maps.Search.Tests.csproj @@ -8,10 +8,12 @@ + + diff --git a/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs b/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs index 65da1886b773d..5619bfdcf9e90 100644 --- a/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs +++ b/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs @@ -5,12 +5,18 @@ using System.Collections.Generic; using System.Threading; using System.Threading.Tasks; -#region Snippet:SearchImportNamespace +#region Snippet:SearchImportNamespaces using Azure.Core.GeoJson; using Azure.Maps.Search; using Azure.Maps.Search.Models; #endregion using Azure.Core.TestFramework; +#region Snippet:SasAuthImportNamespaces +using Azure.Core; +using Azure.ResourceManager; +using Azure.ResourceManager.Maps; +using Azure.ResourceManager.Maps.Models; +#endregion using NUnit.Framework; @@ -40,8 +46,24 @@ public void SearchClientViaAAD() public void SearchClientViaSas() { #region Snippet:InstantiateSearchClientViaSas + // Get your azure access token, for more details of how Azure SDK get your access token, please refer to https://learn.microsoft.com/en-us/dotnet/azure/sdk/authentication?tabs=command-line + TokenCredential cred = new DefaultAzureCredential(); + // Authenticate your client + ArmClient armClient = new ArmClient(cred); + + string subscriptionId = "MyMapsSubscriptionId"; + string resourceGroupName = "MyMapsResourceGroupName"; + string accountName = "MyMapsAccountName"; + ResourceIdentifier mapsAccountResourceId = MapsAccountResource.CreateResourceIdentifier(subscriptionId, resourceGroupName, accountName); + MapsAccountResource mapsAccount = armClient.GetMapsAccountResource(mapsAccountResourceId); + + var principalId = "MyManagedIdentityObjectId"; + int maxRatePerSecond = 500; + var sasContent = new MapsAccountSasContent(MapsSigningKey.PrimaryKey, principalId, maxRatePerSecond, "2023-06-30T04:27:28.734Z", "2023-06-30T12:27:28.734Z"); + var sas = mapsAccount.GetSas(sasContent); + // Create a SearchClient that will authenticate through SAS token - AzureSasCredential sasCredential = new AzureSasCredential(""); + AzureSasCredential sasCredential = new AzureSasCredential(sas.Value.AccountSasToken); MapsSearchClient client = new MapsSearchClient(sasCredential); #endregion } From 0fcb0f56a5ff6113c88b201088dac72f09858e86 Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Fri, 30 Jun 2023 13:10:33 +0800 Subject: [PATCH 07/21] Update comments --- sdk/maps/Azure.Maps.Search/README.md | 4 +++- .../Azure.Maps.Search/tests/Samples/SearchClientSamples.cs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/sdk/maps/Azure.Maps.Search/README.md b/sdk/maps/Azure.Maps.Search/README.md index b8f290279ba39..52f1c776e2bf4 100644 --- a/sdk/maps/Azure.Maps.Search/README.md +++ b/sdk/maps/Azure.Maps.Search/README.md @@ -95,12 +95,14 @@ string accountName = "MyMapsAccountName"; ResourceIdentifier mapsAccountResourceId = MapsAccountResource.CreateResourceIdentifier(subscriptionId, resourceGroupName, accountName); MapsAccountResource mapsAccount = armClient.GetMapsAccountResource(mapsAccountResourceId); +// Assign SAS token information +// Every time you want to SAS token, update the principal ID, max rate, start and expiry time var principalId = "MyManagedIdentityObjectId"; int maxRatePerSecond = 500; var sasContent = new MapsAccountSasContent(MapsSigningKey.PrimaryKey, principalId, maxRatePerSecond, "2023-06-30T04:27:28.734Z", "2023-06-30T12:27:28.734Z"); var sas = mapsAccount.GetSas(sasContent); -// Create a SearchClient that will authenticate through SAS token +// Create a SearchClient that will authenticate via SAS token AzureSasCredential sasCredential = new AzureSasCredential(sas.Value.AccountSasToken); MapsSearchClient client = new MapsSearchClient(sasCredential); ``` diff --git a/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs b/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs index 5619bfdcf9e90..b48594c430a4d 100644 --- a/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs +++ b/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs @@ -57,12 +57,14 @@ public void SearchClientViaSas() ResourceIdentifier mapsAccountResourceId = MapsAccountResource.CreateResourceIdentifier(subscriptionId, resourceGroupName, accountName); MapsAccountResource mapsAccount = armClient.GetMapsAccountResource(mapsAccountResourceId); + // Assign SAS token information + // Every time you want to SAS token, update the principal ID, max rate, start and expiry time var principalId = "MyManagedIdentityObjectId"; int maxRatePerSecond = 500; var sasContent = new MapsAccountSasContent(MapsSigningKey.PrimaryKey, principalId, maxRatePerSecond, "2023-06-30T04:27:28.734Z", "2023-06-30T12:27:28.734Z"); var sas = mapsAccount.GetSas(sasContent); - // Create a SearchClient that will authenticate through SAS token + // Create a SearchClient that will authenticate via SAS token AzureSasCredential sasCredential = new AzureSasCredential(sas.Value.AccountSasToken); MapsSearchClient client = new MapsSearchClient(sasCredential); #endregion From a80f337d4b9ed50c4962bb04f46f1e22f5e0a36f Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Fri, 30 Jun 2023 15:25:46 +0800 Subject: [PATCH 08/21] Update SAS sample --- sdk/maps/Azure.Maps.Search/README.md | 19 +++++++++++++------ .../tests/Samples/SearchClientSamples.cs | 14 +++++++++++--- 2 files changed, 24 insertions(+), 9 deletions(-) diff --git a/sdk/maps/Azure.Maps.Search/README.md b/sdk/maps/Azure.Maps.Search/README.md index 52f1c776e2bf4..5a0bb45a1659e 100644 --- a/sdk/maps/Azure.Maps.Search/README.md +++ b/sdk/maps/Azure.Maps.Search/README.md @@ -58,7 +58,7 @@ MapsSearchClient client = new MapsSearchClient(credential, clientId); Shared access signature (SAS) tokens are authentication tokens created using the JSON Web token (JWT) format and are cryptographically signed to prove authentication for an application to the Azure Maps REST API. -Before integratingSAS token authentication, we need to install `Azure.ResourceManager` and `Azure.ResourceManager.Maps` (version 1.1.0-beta.2 or higher): +Before integrating SAS token authentication, we need to install `Azure.ResourceManager` and `Azure.ResourceManager.Maps` (version `1.1.0-beta.2` or higher): ```powershell dotnet add package Azure.ResourceManager @@ -80,8 +80,7 @@ using Azure.ResourceManager.Maps; using Azure.ResourceManager.Maps.Models; ``` -And then we can get SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it in `MapsSearchClient`: - +And then we can get SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it to `MapsSearchClient`: ```C# Snippet:InstantiateSearchClientViaSas // Get your azure access token, for more details of how Azure SDK get your access token, please refer to https://learn.microsoft.com/en-us/dotnet/azure/sdk/authentication?tabs=command-line @@ -92,15 +91,23 @@ ArmClient armClient = new ArmClient(cred); string subscriptionId = "MyMapsSubscriptionId"; string resourceGroupName = "MyMapsResourceGroupName"; string accountName = "MyMapsAccountName"; + +// Get maps account resource ResourceIdentifier mapsAccountResourceId = MapsAccountResource.CreateResourceIdentifier(subscriptionId, resourceGroupName, accountName); MapsAccountResource mapsAccount = armClient.GetMapsAccountResource(mapsAccountResourceId); // Assign SAS token information // Every time you want to SAS token, update the principal ID, max rate, start and expiry time -var principalId = "MyManagedIdentityObjectId"; +string principalId = "MyManagedIdentityObjectId"; int maxRatePerSecond = 500; -var sasContent = new MapsAccountSasContent(MapsSigningKey.PrimaryKey, principalId, maxRatePerSecond, "2023-06-30T04:27:28.734Z", "2023-06-30T12:27:28.734Z"); -var sas = mapsAccount.GetSas(sasContent); + +// Set start and expiry time for the SAS token in round-trip date/time format +DateTime now = DateTime.Now; +string start = now.ToString("O"); +string expiry = now.AddDays(1).ToString("O"); + +MapsAccountSasContent sasContent = new MapsAccountSasContent(MapsSigningKey.PrimaryKey, principalId, maxRatePerSecond, start, expiry); +Response sas = mapsAccount.GetSas(sasContent); // Create a SearchClient that will authenticate via SAS token AzureSasCredential sasCredential = new AzureSasCredential(sas.Value.AccountSasToken); diff --git a/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs b/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs index b48594c430a4d..ecef905b97443 100644 --- a/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs +++ b/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs @@ -54,15 +54,23 @@ public void SearchClientViaSas() string subscriptionId = "MyMapsSubscriptionId"; string resourceGroupName = "MyMapsResourceGroupName"; string accountName = "MyMapsAccountName"; + + // Get maps account resource ResourceIdentifier mapsAccountResourceId = MapsAccountResource.CreateResourceIdentifier(subscriptionId, resourceGroupName, accountName); MapsAccountResource mapsAccount = armClient.GetMapsAccountResource(mapsAccountResourceId); // Assign SAS token information // Every time you want to SAS token, update the principal ID, max rate, start and expiry time - var principalId = "MyManagedIdentityObjectId"; + string principalId = "MyManagedIdentityObjectId"; int maxRatePerSecond = 500; - var sasContent = new MapsAccountSasContent(MapsSigningKey.PrimaryKey, principalId, maxRatePerSecond, "2023-06-30T04:27:28.734Z", "2023-06-30T12:27:28.734Z"); - var sas = mapsAccount.GetSas(sasContent); + + // Set start and expiry time for the SAS token in round-trip date/time format + DateTime now = DateTime.Now; + string start = now.ToString("O"); + string expiry = now.AddDays(1).ToString("O"); + + MapsAccountSasContent sasContent = new MapsAccountSasContent(MapsSigningKey.PrimaryKey, principalId, maxRatePerSecond, start, expiry); + Response sas = mapsAccount.GetSas(sasContent); // Create a SearchClient that will authenticate via SAS token AzureSasCredential sasCredential = new AzureSasCredential(sas.Value.AccountSasToken); From 08a5647d8dbe14242546ca09e4606dc776d5c3a1 Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Fri, 30 Jun 2023 15:40:52 +0800 Subject: [PATCH 09/21] Update wording --- sdk/maps/Azure.Maps.Search/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/maps/Azure.Maps.Search/README.md b/sdk/maps/Azure.Maps.Search/README.md index 5a0bb45a1659e..8dfb9fa7991ce 100644 --- a/sdk/maps/Azure.Maps.Search/README.md +++ b/sdk/maps/Azure.Maps.Search/README.md @@ -80,7 +80,7 @@ using Azure.ResourceManager.Maps; using Azure.ResourceManager.Maps.Models; ``` -And then we can get SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it to `MapsSearchClient`: +And then we can get SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it to `MapsSearchClient`. In the follow code sample, we fetch a specific maps account resouce, and create a SAS token for 1 day expiry time when the code is executed. ```C# Snippet:InstantiateSearchClientViaSas // Get your azure access token, for more details of how Azure SDK get your access token, please refer to https://learn.microsoft.com/en-us/dotnet/azure/sdk/authentication?tabs=command-line From ee80f96d9017d3e773ff8156a0c4ae544919e597 Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Mon, 3 Jul 2023 13:47:23 +0800 Subject: [PATCH 10/21] Make MapsSasCredentialPolicy internal class --- sdk/maps/Azure.Maps.Common/src/MapsSasCredentialPolicy.cs | 2 +- sdk/maps/Azure.Maps.Search/CHANGELOG.md | 2 +- sdk/maps/Azure.Maps.Search/src/Azure.Maps.Search.csproj | 1 + 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sdk/maps/Azure.Maps.Common/src/MapsSasCredentialPolicy.cs b/sdk/maps/Azure.Maps.Common/src/MapsSasCredentialPolicy.cs index 0170ab93678e8..e87929285bfb6 100644 --- a/sdk/maps/Azure.Maps.Common/src/MapsSasCredentialPolicy.cs +++ b/sdk/maps/Azure.Maps.Common/src/MapsSasCredentialPolicy.cs @@ -7,7 +7,7 @@ namespace Azure.Maps { /// The MapsSasCredentialPolicy used for SAS authentication. - public class MapsSasCredentialPolicy : HttpPipelineSynchronousPolicy + internal sealed class MapsSasCredentialPolicy : HttpPipelineSynchronousPolicy { private readonly string _sasAuthenticationHeader = "Authorization"; private readonly string _sasPrefix = "jwt-sas"; diff --git a/sdk/maps/Azure.Maps.Search/CHANGELOG.md b/sdk/maps/Azure.Maps.Search/CHANGELOG.md index da7540840f391..36e1982ede0ee 100644 --- a/sdk/maps/Azure.Maps.Search/CHANGELOG.md +++ b/sdk/maps/Azure.Maps.Search/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 1.0.0-beta.4 (Unreleased) +## 1.0.0-beta.4 (2023-07-13) ### Features Added diff --git a/sdk/maps/Azure.Maps.Search/src/Azure.Maps.Search.csproj b/sdk/maps/Azure.Maps.Search/src/Azure.Maps.Search.csproj index b3aa650d9c456..5182dcf5af7b6 100644 --- a/sdk/maps/Azure.Maps.Search/src/Azure.Maps.Search.csproj +++ b/sdk/maps/Azure.Maps.Search/src/Azure.Maps.Search.csproj @@ -25,6 +25,7 @@ + From f1c0d457a45db15e8bb3b349148ea3b5b963e83b Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Mon, 3 Jul 2023 16:03:13 +0800 Subject: [PATCH 11/21] Fix test project build error --- .../Azure.Maps.Common/tests/Azure.Maps.Common.Tests.csproj | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sdk/maps/Azure.Maps.Common/tests/Azure.Maps.Common.Tests.csproj b/sdk/maps/Azure.Maps.Common/tests/Azure.Maps.Common.Tests.csproj index 73510a85a651e..628c9a0b729ed 100644 --- a/sdk/maps/Azure.Maps.Common/tests/Azure.Maps.Common.Tests.csproj +++ b/sdk/maps/Azure.Maps.Common/tests/Azure.Maps.Common.Tests.csproj @@ -9,6 +9,11 @@ + + + + + From dd5425d5d126d1d3af02233d9bc136e54cc9e664 Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Mon, 3 Jul 2023 22:28:35 +0800 Subject: [PATCH 12/21] Update autorest.md to avoid generating error --- sdk/maps/Azure.Maps.Search/src/autorest.md | 36 ++++++++++++---------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/sdk/maps/Azure.Maps.Search/src/autorest.md b/sdk/maps/Azure.Maps.Search/src/autorest.md index 02bb1629dbe09..13a97164fdcf7 100644 --- a/sdk/maps/Azure.Maps.Search/src/autorest.md +++ b/sdk/maps/Azure.Maps.Search/src/autorest.md @@ -6,26 +6,10 @@ Run `dotnet build /t:GenerateCode` to generate code. > see https://aka.ms/autorest ```yaml -directive: -- from: swagger-document - where: $.securityDefinitions - transform: | - $["azure_auth"] = $["AADToken"]; - delete $["AADToken"]; -- from: swagger-document - where: '$.security[0]' - transform: | - $["azure_auth"] = $["AADToken"]; - delete $["AADToken"]; -- from: swagger-document - where: $.securityDefinitions - transform: | - $["SharedKey"]["in"] = "header"; input-file: - https://raw.githubusercontent.com/Azure/azure-rest-api-specs/c1260c7a90d503c18b0aeaf29968dfc0b4bf9e11/specification/maps/data-plane/Search/preview/1.0/search.json -title: SearchClient +title: MapsSearchClient openapi-type: data-plane -tag: 1.0-preview add-credentials: true # at some point those credentials will move away to Swagger according to [this](https://github.com/Azure/autorest/issues/3718) credential-default-policy-type: BearerTokenCredentialPolicy @@ -39,3 +23,21 @@ clear-output-folder: true data-plane: true skip-csproj: true ``` + +```yaml +directive: +- from: swagger-document + where: $.securityDefinitions + transform: | + $["azure_auth"] = $["AADToken"]; + delete $["AADToken"]; +- from: swagger-document + where: '$.security[0]' + transform: | + $["azure_auth"] = $["AADToken"]; + delete $["AADToken"]; +- from: swagger-document + where: $.securityDefinitions + transform: | + $["SharedKey"]["in"] = "header"; +``` From 0ee924fde7ea188b32ca57609caab26ee168c604 Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Mon, 3 Jul 2023 23:14:05 +0800 Subject: [PATCH 13/21] Support SAS token auth for geolocation --- sdk/maps/Azure.Maps.Geolocation/CHANGELOG.md | 6 +- sdk/maps/Azure.Maps.Geolocation/README.md | 55 +++++++++++++++++++ .../Azure.Maps.Geolocation.netstandard2.0.cs | 2 + .../src/Azure.Maps.Geolocation.csproj | 4 ++ .../src/MapsGeolocationClient.cs | 29 ++++++++++ .../tests/Azure.Maps.Geolocation.Tests.csproj | 1 + .../tests/Samples/GeolocationClientSamples.cs | 46 ++++++++++++++-- 7 files changed, 134 insertions(+), 9 deletions(-) diff --git a/sdk/maps/Azure.Maps.Geolocation/CHANGELOG.md b/sdk/maps/Azure.Maps.Geolocation/CHANGELOG.md index ca636573527d1..63529f046ed7f 100644 --- a/sdk/maps/Azure.Maps.Geolocation/CHANGELOG.md +++ b/sdk/maps/Azure.Maps.Geolocation/CHANGELOG.md @@ -4,11 +4,7 @@ ### Features Added -### Breaking Changes - -### Bugs Fixed - -### Other Changes +- Support SAS authentication ## 1.0.0-beta.1 (2022-10-11) diff --git a/sdk/maps/Azure.Maps.Geolocation/README.md b/sdk/maps/Azure.Maps.Geolocation/README.md index ffa23b6c885a7..2c2c58905f69f 100644 --- a/sdk/maps/Azure.Maps.Geolocation/README.md +++ b/sdk/maps/Azure.Maps.Geolocation/README.md @@ -54,6 +54,61 @@ string clientId = ""; MapsGeolocationClient client = new MapsGeolocationClient(credential, clientId); ``` +#### Shared Access Signature (SAS) Authentication + +Shared access signature (SAS) tokens are authentication tokens created using the JSON Web token (JWT) format and are cryptographically signed to prove authentication for an application to the Azure Maps REST API. + +Before integrating SAS token authentication, we need to install `Azure.ResourceManager` and `Azure.ResourceManager.Maps` (version `1.1.0-beta.2` or higher): + +```powershell +dotnet add package Azure.ResourceManager +dotnet add package Azure.ResourceManager.Maps --prerelease +``` + +In the code, we need to import the following lines for both Azure Maps ResourceManager: + +```C# Snippet:SasAuthImportNamespaces +using Azure.Maps.Geolocation; +using Azure.Core; +using Azure.ResourceManager; +using Azure.ResourceManager.Maps; +using Azure.ResourceManager.Maps.Models; +``` + +And then we can get SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it to `MapsSearchClient`. In the follow code sample, we fetch a specific maps account resouce, and create a SAS token for 1 day expiry time when the code is executed. + +```C# Snippet:InstantiateGeolocationClientViaSas +// Get your azure access token, for more details of how Azure SDK get your access token, please refer to https://learn.microsoft.com/en-us/dotnet/azure/sdk/authentication?tabs=command-line +TokenCredential cred = new DefaultAzureCredential(); +// Authenticate your client +ArmClient armClient = new ArmClient(cred); + +string subscriptionId = "MyMapsSubscriptionId"; +string resourceGroupName = "MyMapsResourceGroupName"; +string accountName = "MyMapsAccountName"; + +// Get maps account resource +ResourceIdentifier mapsAccountResourceId = MapsAccountResource.CreateResourceIdentifier(subscriptionId, resourceGroupName, accountName); +MapsAccountResource mapsAccount = armClient.GetMapsAccountResource(mapsAccountResourceId); + +// Assign SAS token information +// Every time you want to SAS token, update the principal ID, max rate, start and expiry time +string principalId = "MyManagedIdentityObjectId"; +int maxRatePerSecond = 500; + +// Set start and expiry time for the SAS token in round-trip date/time format +DateTime now = DateTime.Now; +string start = now.ToString("O"); +string expiry = now.AddDays(1).ToString("O"); + +MapsAccountSasContent sasContent = new MapsAccountSasContent(MapsSigningKey.PrimaryKey, principalId, maxRatePerSecond, start, expiry); +Response sas = mapsAccount.GetSas(sasContent); + +// Create a SearchClient that will authenticate via SAS token +AzureSasCredential sasCredential = new AzureSasCredential(sas.Value.AccountSasToken); +MapsGeolocationClient client = new MapsGeolocationClient(sasCredential); +``` + ## Key concepts `MapsGeolocationClient` is designed for: diff --git a/sdk/maps/Azure.Maps.Geolocation/api/Azure.Maps.Geolocation.netstandard2.0.cs b/sdk/maps/Azure.Maps.Geolocation/api/Azure.Maps.Geolocation.netstandard2.0.cs index 919063126f3f1..7714d289502b3 100644 --- a/sdk/maps/Azure.Maps.Geolocation/api/Azure.Maps.Geolocation.netstandard2.0.cs +++ b/sdk/maps/Azure.Maps.Geolocation/api/Azure.Maps.Geolocation.netstandard2.0.cs @@ -11,6 +11,8 @@ public partial class MapsGeolocationClient protected MapsGeolocationClient() { } public MapsGeolocationClient(Azure.AzureKeyCredential credential) { } public MapsGeolocationClient(Azure.AzureKeyCredential credential, Azure.Maps.Geolocation.MapsGeolocationClientOptions options) { } + public MapsGeolocationClient(Azure.AzureSasCredential credential) { } + public MapsGeolocationClient(Azure.AzureSasCredential credential, Azure.Maps.Geolocation.MapsGeolocationClientOptions options) { } public MapsGeolocationClient(Azure.Core.TokenCredential credential, string clientId) { } public MapsGeolocationClient(Azure.Core.TokenCredential credential, string clientId, Azure.Maps.Geolocation.MapsGeolocationClientOptions options) { } public virtual Azure.Response GetCountryCode(System.Net.IPAddress ipAddress, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } diff --git a/sdk/maps/Azure.Maps.Geolocation/src/Azure.Maps.Geolocation.csproj b/sdk/maps/Azure.Maps.Geolocation/src/Azure.Maps.Geolocation.csproj index 4aa01e76dd414..c55214b9ea425 100644 --- a/sdk/maps/Azure.Maps.Geolocation/src/Azure.Maps.Geolocation.csproj +++ b/sdk/maps/Azure.Maps.Geolocation/src/Azure.Maps.Geolocation.csproj @@ -20,4 +20,8 @@ + + + + diff --git a/sdk/maps/Azure.Maps.Geolocation/src/MapsGeolocationClient.cs b/sdk/maps/Azure.Maps.Geolocation/src/MapsGeolocationClient.cs index a84e567f05946..d184d19adefb2 100644 --- a/sdk/maps/Azure.Maps.Geolocation/src/MapsGeolocationClient.cs +++ b/sdk/maps/Azure.Maps.Geolocation/src/MapsGeolocationClient.cs @@ -95,6 +95,35 @@ public MapsGeolocationClient(TokenCredential credential, string clientId, MapsGe RestClient = new GeolocationRestClient(_clientDiagnostics, _pipeline, endpoint, clientId, options.Version); } + /// Initializes a new instance of MapsGeolocationClient. + /// The Shared Access Signature credential used to connect to Azure. This signature + /// can be constructed using the . + public MapsGeolocationClient(AzureSasCredential credential) + { + Argument.AssertNotNull(credential, nameof(credential)); + + var endpoint = new Uri("https://atlas.microsoft.com"); + var options = new MapsGeolocationClientOptions(); + _clientDiagnostics = new ClientDiagnostics(options); + _pipeline = HttpPipelineBuilder.Build(options, new MapsSasCredentialPolicy(credential)); + RestClient = new GeolocationRestClient(_clientDiagnostics, _pipeline, endpoint, null, options.Version); + } + + /// Initializes a new instance of MapsGeolocationClient. + /// The Shared Access Signature credential used to connect to Azure. This signature + /// can be constructed using the . + /// The options for configuring the client. + public MapsGeolocationClient(AzureSasCredential credential, MapsGeolocationClientOptions options) + { + Argument.AssertNotNull(credential, nameof(credential)); + + var endpoint = options.Endpoint; + options ??= new MapsGeolocationClientOptions(); + _clientDiagnostics = new ClientDiagnostics(options); + _pipeline = HttpPipelineBuilder.Build(options, new MapsSasCredentialPolicy(credential)); + RestClient = new GeolocationRestClient(_clientDiagnostics, _pipeline, endpoint, null, options.Version); + } + /// /// This service will return the ISO country code for the provided IP address. Developers can use this information to block or alter certain content based on geographical locations where the application is being viewed from. /// diff --git a/sdk/maps/Azure.Maps.Geolocation/tests/Azure.Maps.Geolocation.Tests.csproj b/sdk/maps/Azure.Maps.Geolocation/tests/Azure.Maps.Geolocation.Tests.csproj index 448939396e228..65b84a9f93ca9 100644 --- a/sdk/maps/Azure.Maps.Geolocation/tests/Azure.Maps.Geolocation.Tests.csproj +++ b/sdk/maps/Azure.Maps.Geolocation/tests/Azure.Maps.Geolocation.Tests.csproj @@ -9,6 +9,7 @@ + diff --git a/sdk/maps/Azure.Maps.Geolocation/tests/Samples/GeolocationClientSamples.cs b/sdk/maps/Azure.Maps.Geolocation/tests/Samples/GeolocationClientSamples.cs index 7a41f4f5d0717..c970759aeb17f 100644 --- a/sdk/maps/Azure.Maps.Geolocation/tests/Samples/GeolocationClientSamples.cs +++ b/sdk/maps/Azure.Maps.Geolocation/tests/Samples/GeolocationClientSamples.cs @@ -3,12 +3,15 @@ using System; using System.Net; -using System.Collections.Generic; -using System.IO; -using Azure.Core; -using Azure.Maps.Geolocation; using Azure.Core.TestFramework; using NUnit.Framework; +#region Snippet:SasAuthImportNamespaces +using Azure.Maps.Geolocation; +using Azure.Core; +using Azure.ResourceManager; +using Azure.ResourceManager.Maps; +using Azure.ResourceManager.Maps.Models; +#endregion namespace Azure.Maps.Geolocation.Tests { @@ -38,6 +41,41 @@ public void GeolocationClientViaSubscriptionKey() #endregion } + public void GeolocationClientViaSas() + { + #region Snippet:InstantiateGeolocationClientViaSas + // Get your azure access token, for more details of how Azure SDK get your access token, please refer to https://learn.microsoft.com/en-us/dotnet/azure/sdk/authentication?tabs=command-line + TokenCredential cred = new DefaultAzureCredential(); + // Authenticate your client + ArmClient armClient = new ArmClient(cred); + + string subscriptionId = "MyMapsSubscriptionId"; + string resourceGroupName = "MyMapsResourceGroupName"; + string accountName = "MyMapsAccountName"; + + // Get maps account resource + ResourceIdentifier mapsAccountResourceId = MapsAccountResource.CreateResourceIdentifier(subscriptionId, resourceGroupName, accountName); + MapsAccountResource mapsAccount = armClient.GetMapsAccountResource(mapsAccountResourceId); + + // Assign SAS token information + // Every time you want to SAS token, update the principal ID, max rate, start and expiry time + string principalId = "MyManagedIdentityObjectId"; + int maxRatePerSecond = 500; + + // Set start and expiry time for the SAS token in round-trip date/time format + DateTime now = DateTime.Now; + string start = now.ToString("O"); + string expiry = now.AddDays(1).ToString("O"); + + MapsAccountSasContent sasContent = new MapsAccountSasContent(MapsSigningKey.PrimaryKey, principalId, maxRatePerSecond, start, expiry); + Response sas = mapsAccount.GetSas(sasContent); + + // Create a SearchClient that will authenticate via SAS token + AzureSasCredential sasCredential = new AzureSasCredential(sas.Value.AccountSasToken); + MapsGeolocationClient client = new MapsGeolocationClient(sasCredential); + #endregion + } + [Test] public void GetCountryCodeTest() { From 13d7e555280f6c79415e091273e11d95bdf9ab3a Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Mon, 3 Jul 2023 23:14:30 +0800 Subject: [PATCH 14/21] Update search readme --- sdk/maps/Azure.Maps.Search/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/maps/Azure.Maps.Search/CHANGELOG.md b/sdk/maps/Azure.Maps.Search/CHANGELOG.md index 36e1982ede0ee..da7540840f391 100644 --- a/sdk/maps/Azure.Maps.Search/CHANGELOG.md +++ b/sdk/maps/Azure.Maps.Search/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 1.0.0-beta.4 (2023-07-13) +## 1.0.0-beta.4 (Unreleased) ### Features Added From 321c1069967901a14c85d2557b49ba7484e38b4b Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Mon, 3 Jul 2023 23:33:59 +0800 Subject: [PATCH 15/21] Update geolocation code snippet --- sdk/maps/Azure.Maps.Geolocation/README.md | 4 ++-- .../tests/Azure.Maps.Geolocation.Tests.csproj | 1 + .../tests/Samples/GeolocationClientSamples.cs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/sdk/maps/Azure.Maps.Geolocation/README.md b/sdk/maps/Azure.Maps.Geolocation/README.md index 2c2c58905f69f..1ae6f662f204d 100644 --- a/sdk/maps/Azure.Maps.Geolocation/README.md +++ b/sdk/maps/Azure.Maps.Geolocation/README.md @@ -67,7 +67,7 @@ dotnet add package Azure.ResourceManager.Maps --prerelease In the code, we need to import the following lines for both Azure Maps ResourceManager: -```C# Snippet:SasAuthImportNamespaces +```C# Snippet:GeolocationSasAuthImportNamespaces using Azure.Maps.Geolocation; using Azure.Core; using Azure.ResourceManager; @@ -75,7 +75,7 @@ using Azure.ResourceManager.Maps; using Azure.ResourceManager.Maps.Models; ``` -And then we can get SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it to `MapsSearchClient`. In the follow code sample, we fetch a specific maps account resouce, and create a SAS token for 1 day expiry time when the code is executed. +And then we can get SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it to `MapsSearchClient`. In the follow code sample, we fetch a specific maps account resource, and create a SAS token for 1 day expiry time when the code is executed. ```C# Snippet:InstantiateGeolocationClientViaSas // Get your azure access token, for more details of how Azure SDK get your access token, please refer to https://learn.microsoft.com/en-us/dotnet/azure/sdk/authentication?tabs=command-line diff --git a/sdk/maps/Azure.Maps.Geolocation/tests/Azure.Maps.Geolocation.Tests.csproj b/sdk/maps/Azure.Maps.Geolocation/tests/Azure.Maps.Geolocation.Tests.csproj index 65b84a9f93ca9..25b4eed483136 100644 --- a/sdk/maps/Azure.Maps.Geolocation/tests/Azure.Maps.Geolocation.Tests.csproj +++ b/sdk/maps/Azure.Maps.Geolocation/tests/Azure.Maps.Geolocation.Tests.csproj @@ -17,6 +17,7 @@ + diff --git a/sdk/maps/Azure.Maps.Geolocation/tests/Samples/GeolocationClientSamples.cs b/sdk/maps/Azure.Maps.Geolocation/tests/Samples/GeolocationClientSamples.cs index c970759aeb17f..c2bd2d9b4e0ba 100644 --- a/sdk/maps/Azure.Maps.Geolocation/tests/Samples/GeolocationClientSamples.cs +++ b/sdk/maps/Azure.Maps.Geolocation/tests/Samples/GeolocationClientSamples.cs @@ -5,7 +5,7 @@ using System.Net; using Azure.Core.TestFramework; using NUnit.Framework; -#region Snippet:SasAuthImportNamespaces +#region Snippet:GeolocationSasAuthImportNamespaces using Azure.Maps.Geolocation; using Azure.Core; using Azure.ResourceManager; From 894dba07a6511fbba5af7a6de48fd9ec1acacd2e Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Mon, 3 Jul 2023 23:34:25 +0800 Subject: [PATCH 16/21] Update Search code snippet --- sdk/maps/Azure.Maps.Search/README.md | 6 +++--- .../Azure.Maps.Search/tests/Samples/SearchClientSamples.cs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sdk/maps/Azure.Maps.Search/README.md b/sdk/maps/Azure.Maps.Search/README.md index 8dfb9fa7991ce..72cb015247967 100644 --- a/sdk/maps/Azure.Maps.Search/README.md +++ b/sdk/maps/Azure.Maps.Search/README.md @@ -67,20 +67,20 @@ dotnet add package Azure.ResourceManager.Maps --prerelease In the code, we need to import the following lines for both Azure Maps SDK and ResourceManager: -```C# Snippet:SearchImportNamespaces +```C# Snippet:RenderImportNamespaces using Azure.Core.GeoJson; using Azure.Maps.Search; using Azure.Maps.Search.Models; ``` -```C# Snippet:SasAuthImportNamespaces +```C# Snippet:SearchSasAuthImportNamespaces using Azure.Core; using Azure.ResourceManager; using Azure.ResourceManager.Maps; using Azure.ResourceManager.Maps.Models; ``` -And then we can get SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it to `MapsSearchClient`. In the follow code sample, we fetch a specific maps account resouce, and create a SAS token for 1 day expiry time when the code is executed. +And then we can get SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it to `MapsSearchClient`. In the follow code sample, we fetch a specific maps account resource, and create a SAS token for 1 day expiry time when the code is executed. ```C# Snippet:InstantiateSearchClientViaSas // Get your azure access token, for more details of how Azure SDK get your access token, please refer to https://learn.microsoft.com/en-us/dotnet/azure/sdk/authentication?tabs=command-line diff --git a/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs b/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs index ecef905b97443..a1907e3ebce78 100644 --- a/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs +++ b/sdk/maps/Azure.Maps.Search/tests/Samples/SearchClientSamples.cs @@ -11,7 +11,7 @@ using Azure.Maps.Search.Models; #endregion using Azure.Core.TestFramework; -#region Snippet:SasAuthImportNamespaces +#region Snippet:SearchSasAuthImportNamespaces using Azure.Core; using Azure.ResourceManager; using Azure.ResourceManager.Maps; From 2dcb028545574fbf349cb3ee5c585fb3beeebc70 Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Mon, 3 Jul 2023 23:44:45 +0800 Subject: [PATCH 17/21] Update rendering service for SAS auth --- sdk/maps/Azure.Maps.Rendering/CHANGELOG.md | 4 ++ sdk/maps/Azure.Maps.Rendering/README.md | 58 +++++++++++++++++++ ...apsRenderingTilesImageriesImagesSamples.md | 2 +- .../src/Azure.Maps.Rendering.csproj | 1 + .../src/MapsRenderingClient.cs | 29 ++++++++++ .../tests/Azure.Maps.Rendering.Tests.csproj | 2 + .../tests/Samples/RenderingClientSamples.cs | 44 +++++++++++++- 7 files changed, 137 insertions(+), 3 deletions(-) diff --git a/sdk/maps/Azure.Maps.Rendering/CHANGELOG.md b/sdk/maps/Azure.Maps.Rendering/CHANGELOG.md index cd045be75d46b..2dc5b521fe807 100644 --- a/sdk/maps/Azure.Maps.Rendering/CHANGELOG.md +++ b/sdk/maps/Azure.Maps.Rendering/CHANGELOG.md @@ -2,6 +2,10 @@ ## 1.0.0-beta.2 (Unreleased) +### Features Added + +- Support SAS authentication + ### Other Changes - Deprecate Elevation tile enum diff --git a/sdk/maps/Azure.Maps.Rendering/README.md b/sdk/maps/Azure.Maps.Rendering/README.md index c2528fdecb551..3e06a911d60d8 100644 --- a/sdk/maps/Azure.Maps.Rendering/README.md +++ b/sdk/maps/Azure.Maps.Rendering/README.md @@ -56,6 +56,64 @@ string clientId = ""; MapsRenderingClient client = new MapsRenderingClient(credential, clientId); ``` +#### Shared Access Signature (SAS) Authentication + +Shared access signature (SAS) tokens are authentication tokens created using the JSON Web token (JWT) format and are cryptographically signed to prove authentication for an application to the Azure Maps REST API. + +Before integrating SAS token authentication, we need to install `Azure.ResourceManager` and `Azure.ResourceManager.Maps` (version `1.1.0-beta.2` or higher): + +```powershell +dotnet add package Azure.ResourceManager +dotnet add package Azure.ResourceManager.Maps --prerelease +``` + +In the code, we need to import the following lines for both Azure Maps SDK and ResourceManager: + +```C# Snippet:RenderImportNamespaces +using Azure.Maps.Rendering; +``` + +```C# Snippet:RenderSasAuthImportNamespaces +using Azure.Core; +using Azure.ResourceManager; +using Azure.ResourceManager.Maps; +using Azure.ResourceManager.Maps.Models; +``` + +And then we can get SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it to `MapsSearchClient`. In the follow code sample, we fetch a specific maps account resource, and create a SAS token for 1 day expiry time when the code is executed. + +```C# Snippet:InstantiateRenderingClientViaSas +// Get your azure access token, for more details of how Azure SDK get your access token, please refer to https://learn.microsoft.com/en-us/dotnet/azure/sdk/authentication?tabs=command-line +TokenCredential cred = new DefaultAzureCredential(); +// Authenticate your client +ArmClient armClient = new ArmClient(cred); + +string subscriptionId = "MyMapsSubscriptionId"; +string resourceGroupName = "MyMapsResourceGroupName"; +string accountName = "MyMapsAccountName"; + +// Get maps account resource +ResourceIdentifier mapsAccountResourceId = MapsAccountResource.CreateResourceIdentifier(subscriptionId, resourceGroupName, accountName); +MapsAccountResource mapsAccount = armClient.GetMapsAccountResource(mapsAccountResourceId); + +// Assign SAS token information +// Every time you want to SAS token, update the principal ID, max rate, start and expiry time +string principalId = "MyManagedIdentityObjectId"; +int maxRatePerSecond = 500; + +// Set start and expiry time for the SAS token in round-trip date/time format +DateTime now = DateTime.Now; +string start = now.ToString("O"); +string expiry = now.AddDays(1).ToString("O"); + +MapsAccountSasContent sasContent = new MapsAccountSasContent(MapsSigningKey.PrimaryKey, principalId, maxRatePerSecond, start, expiry); +Response sas = mapsAccount.GetSas(sasContent); + +// Create a SearchClient that will authenticate via SAS token +AzureSasCredential sasCredential = new AzureSasCredential(sas.Value.AccountSasToken); +MapsRenderingClient client = new MapsRenderingClient(sasCredential); +``` + ## Key concepts MapsRenderingClient is designed for: diff --git a/sdk/maps/Azure.Maps.Rendering/samples/MapsRenderingTilesImageriesImagesSamples.md b/sdk/maps/Azure.Maps.Rendering/samples/MapsRenderingTilesImageriesImagesSamples.md index e1ac14b8a767c..7d0690ff14eeb 100644 --- a/sdk/maps/Azure.Maps.Rendering/samples/MapsRenderingTilesImageriesImagesSamples.md +++ b/sdk/maps/Azure.Maps.Rendering/samples/MapsRenderingTilesImageriesImagesSamples.md @@ -2,7 +2,7 @@ ## Import the namespaces -```C# Snippet:RenderImportNamespace +```C# Snippet:RenderImportNamespaces using Azure.Maps.Rendering; ``` diff --git a/sdk/maps/Azure.Maps.Rendering/src/Azure.Maps.Rendering.csproj b/sdk/maps/Azure.Maps.Rendering/src/Azure.Maps.Rendering.csproj index 06e85b9027a8e..df68227058db9 100644 --- a/sdk/maps/Azure.Maps.Rendering/src/Azure.Maps.Rendering.csproj +++ b/sdk/maps/Azure.Maps.Rendering/src/Azure.Maps.Rendering.csproj @@ -24,6 +24,7 @@ + diff --git a/sdk/maps/Azure.Maps.Rendering/src/MapsRenderingClient.cs b/sdk/maps/Azure.Maps.Rendering/src/MapsRenderingClient.cs index 55de15ae96da1..3c71b1f3e1295 100644 --- a/sdk/maps/Azure.Maps.Rendering/src/MapsRenderingClient.cs +++ b/sdk/maps/Azure.Maps.Rendering/src/MapsRenderingClient.cs @@ -92,6 +92,35 @@ public MapsRenderingClient(TokenCredential credential, string clientId, MapsRend restClient = new RenderRestClient(_clientDiagnostics, _pipeline, endpoint, clientId, options.Version); } + /// Initializes a new instance of MapsRenderingClient. + /// The Shared Access Signature credential used to connect to Azure. This signature + /// can be constructed using the . + public MapsRenderingClient(AzureSasCredential credential) + { + Argument.AssertNotNull(credential, nameof(credential)); + + var endpoint = new Uri("https://atlas.microsoft.com"); + var options = new MapsRenderingClientOptions(); + _clientDiagnostics = new ClientDiagnostics(options); + _pipeline = HttpPipelineBuilder.Build(options, new MapsSasCredentialPolicy(credential)); + restClient = new RenderRestClient(_clientDiagnostics, _pipeline, endpoint, null, options.Version); + } + + /// Initializes a new instance of MapsRenderingClient. + /// The Shared Access Signature credential used to connect to Azure. This signature + /// can be constructed using the . + /// The options for configuring the client. + public MapsRenderingClient(AzureSasCredential credential, MapsRenderingClientOptions options) + { + Argument.AssertNotNull(credential, nameof(credential)); + + var endpoint = options.Endpoint; + options ??= new MapsRenderingClientOptions(); + _clientDiagnostics = new ClientDiagnostics(options); + _pipeline = HttpPipelineBuilder.Build(options, new MapsSasCredentialPolicy(credential)); + restClient = new RenderRestClient(_clientDiagnostics, _pipeline, endpoint, null, options.Version); + } + /// Initializes a new instance of MapsRenderingClient. /// The handler for diagnostic messaging in the client. /// The HTTP pipeline for sending and receiving REST requests and responses. diff --git a/sdk/maps/Azure.Maps.Rendering/tests/Azure.Maps.Rendering.Tests.csproj b/sdk/maps/Azure.Maps.Rendering/tests/Azure.Maps.Rendering.Tests.csproj index cba1b24e513e2..0672c74c5042d 100644 --- a/sdk/maps/Azure.Maps.Rendering/tests/Azure.Maps.Rendering.Tests.csproj +++ b/sdk/maps/Azure.Maps.Rendering/tests/Azure.Maps.Rendering.Tests.csproj @@ -10,6 +10,7 @@ + @@ -17,6 +18,7 @@ + diff --git a/sdk/maps/Azure.Maps.Rendering/tests/Samples/RenderingClientSamples.cs b/sdk/maps/Azure.Maps.Rendering/tests/Samples/RenderingClientSamples.cs index c0c2b6c9da40d..29e3606b8f08b 100644 --- a/sdk/maps/Azure.Maps.Rendering/tests/Samples/RenderingClientSamples.cs +++ b/sdk/maps/Azure.Maps.Rendering/tests/Samples/RenderingClientSamples.cs @@ -7,13 +7,18 @@ #region Snippet:SaveToFile using System.IO; #endregion -#region Snippet:RenderImportNamespace +#region Snippet:RenderImportNamespaces using Azure.Maps.Rendering; #endregion -using Azure.Core; using Azure.Core.GeoJson; using Azure.Core.TestFramework; using NUnit.Framework; +#region Snippet:RenderSasAuthImportNamespaces +using Azure.Core; +using Azure.ResourceManager; +using Azure.ResourceManager.Maps; +using Azure.ResourceManager.Maps.Models; +#endregion namespace Azure.Maps.Rendering.Tests { @@ -43,6 +48,41 @@ public void RenderingClientViaSubscriptionKey() #endregion } + public void RenderingClientViaSas() + { + #region Snippet:InstantiateRenderingClientViaSas + // Get your azure access token, for more details of how Azure SDK get your access token, please refer to https://learn.microsoft.com/en-us/dotnet/azure/sdk/authentication?tabs=command-line + TokenCredential cred = new DefaultAzureCredential(); + // Authenticate your client + ArmClient armClient = new ArmClient(cred); + + string subscriptionId = "MyMapsSubscriptionId"; + string resourceGroupName = "MyMapsResourceGroupName"; + string accountName = "MyMapsAccountName"; + + // Get maps account resource + ResourceIdentifier mapsAccountResourceId = MapsAccountResource.CreateResourceIdentifier(subscriptionId, resourceGroupName, accountName); + MapsAccountResource mapsAccount = armClient.GetMapsAccountResource(mapsAccountResourceId); + + // Assign SAS token information + // Every time you want to SAS token, update the principal ID, max rate, start and expiry time + string principalId = "MyManagedIdentityObjectId"; + int maxRatePerSecond = 500; + + // Set start and expiry time for the SAS token in round-trip date/time format + DateTime now = DateTime.Now; + string start = now.ToString("O"); + string expiry = now.AddDays(1).ToString("O"); + + MapsAccountSasContent sasContent = new MapsAccountSasContent(MapsSigningKey.PrimaryKey, principalId, maxRatePerSecond, start, expiry); + Response sas = mapsAccount.GetSas(sasContent); + + // Create a SearchClient that will authenticate via SAS token + AzureSasCredential sasCredential = new AzureSasCredential(sas.Value.AccountSasToken); + MapsRenderingClient client = new MapsRenderingClient(sasCredential); + #endregion + } + [Test] public void RenderingStaticImages() { From 5b35df05e73af71dc39b88b1165a15b5a6a451fb Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Tue, 4 Jul 2023 00:09:56 +0800 Subject: [PATCH 18/21] Fix typos --- sdk/maps/Azure.Maps.Geolocation/README.md | 2 +- sdk/maps/Azure.Maps.Rendering/README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/maps/Azure.Maps.Geolocation/README.md b/sdk/maps/Azure.Maps.Geolocation/README.md index 1ae6f662f204d..27ffaf853a4e5 100644 --- a/sdk/maps/Azure.Maps.Geolocation/README.md +++ b/sdk/maps/Azure.Maps.Geolocation/README.md @@ -75,7 +75,7 @@ using Azure.ResourceManager.Maps; using Azure.ResourceManager.Maps.Models; ``` -And then we can get SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it to `MapsSearchClient`. In the follow code sample, we fetch a specific maps account resource, and create a SAS token for 1 day expiry time when the code is executed. +And then we can get SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it to `MapsGeolocationClient`. In the follow code sample, we fetch a specific maps account resource, and create a SAS token for 1 day expiry time when the code is executed. ```C# Snippet:InstantiateGeolocationClientViaSas // Get your azure access token, for more details of how Azure SDK get your access token, please refer to https://learn.microsoft.com/en-us/dotnet/azure/sdk/authentication?tabs=command-line diff --git a/sdk/maps/Azure.Maps.Rendering/README.md b/sdk/maps/Azure.Maps.Rendering/README.md index 3e06a911d60d8..b4c588a750dd7 100644 --- a/sdk/maps/Azure.Maps.Rendering/README.md +++ b/sdk/maps/Azure.Maps.Rendering/README.md @@ -80,7 +80,7 @@ using Azure.ResourceManager.Maps; using Azure.ResourceManager.Maps.Models; ``` -And then we can get SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it to `MapsSearchClient`. In the follow code sample, we fetch a specific maps account resource, and create a SAS token for 1 day expiry time when the code is executed. +And then we can get SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it to `MapsRenderingClient`. In the follow code sample, we fetch a specific maps account resource, and create a SAS token for 1 day expiry time when the code is executed. ```C# Snippet:InstantiateRenderingClientViaSas // Get your azure access token, for more details of how Azure SDK get your access token, please refer to https://learn.microsoft.com/en-us/dotnet/azure/sdk/authentication?tabs=command-line From 60504b7bc9d29faa466c8f2e720e6b03fc59dd43 Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Tue, 4 Jul 2023 00:10:13 +0800 Subject: [PATCH 19/21] Support SAS auth for Routing service --- sdk/maps/Azure.Maps.Routing/CHANGELOG.md | 4 ++ sdk/maps/Azure.Maps.Routing/README.md | 60 +++++++++++++++++++ .../api/Azure.Maps.Routing.netstandard2.0.cs | 2 + .../samples/RouteDirectionsSamples.md | 2 +- .../samples/RouteMatrixSamples.md | 2 +- .../samples/RouteRangeSamples.md | 2 +- .../src/Azure.Maps.Routing.csproj | 4 ++ .../src/MapsRoutingClient.cs | 29 +++++++++ .../tests/Azure.Maps.Routing.Tests.csproj | 2 + .../tests/Samples/RouteClientSamples.cs | 44 +++++++++++++- 10 files changed, 146 insertions(+), 5 deletions(-) diff --git a/sdk/maps/Azure.Maps.Routing/CHANGELOG.md b/sdk/maps/Azure.Maps.Routing/CHANGELOG.md index b4be0c54cc1d5..0ad8a24d2ac65 100644 --- a/sdk/maps/Azure.Maps.Routing/CHANGELOG.md +++ b/sdk/maps/Azure.Maps.Routing/CHANGELOG.md @@ -2,6 +2,10 @@ ## 1.0.0-beta.2 (Unreleased) +### Features Added + +- Support SAS authentication + ### Bugs Fixed - Update dependency libraries versions diff --git a/sdk/maps/Azure.Maps.Routing/README.md b/sdk/maps/Azure.Maps.Routing/README.md index 8a7ec3dd53fb3..5f8241d5c4f3d 100644 --- a/sdk/maps/Azure.Maps.Routing/README.md +++ b/sdk/maps/Azure.Maps.Routing/README.md @@ -56,6 +56,66 @@ string clientId = ""; MapsRoutingClient client = new MapsRoutingClient(credential, clientId); ``` +#### Shared Access Signature (SAS) Authentication + +Shared access signature (SAS) tokens are authentication tokens created using the JSON Web token (JWT) format and are cryptographically signed to prove authentication for an application to the Azure Maps REST API. + +Before integrating SAS token authentication, we need to install `Azure.ResourceManager` and `Azure.ResourceManager.Maps` (version `1.1.0-beta.2` or higher): + +```powershell +dotnet add package Azure.ResourceManager +dotnet add package Azure.ResourceManager.Maps --prerelease +``` + +In the code, we need to import the following lines for both Azure Maps SDK and ResourceManager: + +```C# Snippet:RouteImportNamespaces +using Azure.Core.GeoJson; +using Azure.Maps.Routing; +using Azure.Maps.Routing.Models; +``` + +```C# Snippet:RouteSasAuthImportNamespaces +using Azure.Core; +using Azure.ResourceManager; +using Azure.ResourceManager.Maps; +using Azure.ResourceManager.Maps.Models; +``` + +And then we can get SAS token via [List Sas](https://learn.microsoft.com/rest/api/maps-management/accounts/list-sas?tabs=HTTP) API and assign it to `MapsRoutingClient`. In the follow code sample, we fetch a specific maps account resource, and create a SAS token for 1 day expiry time when the code is executed. + +```C# Snippet:InstantiateRouteClientViaSas +// Get your azure access token, for more details of how Azure SDK get your access token, please refer to https://learn.microsoft.com/en-us/dotnet/azure/sdk/authentication?tabs=command-line +TokenCredential cred = new DefaultAzureCredential(); +// Authenticate your client +ArmClient armClient = new ArmClient(cred); + +string subscriptionId = "MyMapsSubscriptionId"; +string resourceGroupName = "MyMapsResourceGroupName"; +string accountName = "MyMapsAccountName"; + +// Get maps account resource +ResourceIdentifier mapsAccountResourceId = MapsAccountResource.CreateResourceIdentifier(subscriptionId, resourceGroupName, accountName); +MapsAccountResource mapsAccount = armClient.GetMapsAccountResource(mapsAccountResourceId); + +// Assign SAS token information +// Every time you want to SAS token, update the principal ID, max rate, start and expiry time +string principalId = "MyManagedIdentityObjectId"; +int maxRatePerSecond = 500; + +// Set start and expiry time for the SAS token in round-trip date/time format +DateTime now = DateTime.Now; +string start = now.ToString("O"); +string expiry = now.AddDays(1).ToString("O"); + +MapsAccountSasContent sasContent = new MapsAccountSasContent(MapsSigningKey.PrimaryKey, principalId, maxRatePerSecond, start, expiry); +Response sas = mapsAccount.GetSas(sasContent); + +// Create a SearchClient that will authenticate via SAS token +AzureSasCredential sasCredential = new AzureSasCredential(sas.Value.AccountSasToken); +MapsRoutingClient client = new MapsRoutingClient(sasCredential); +``` + ## Key concepts `MapsRoutingClient` is designed to: diff --git a/sdk/maps/Azure.Maps.Routing/api/Azure.Maps.Routing.netstandard2.0.cs b/sdk/maps/Azure.Maps.Routing/api/Azure.Maps.Routing.netstandard2.0.cs index d302268745a88..60a177e32da95 100644 --- a/sdk/maps/Azure.Maps.Routing/api/Azure.Maps.Routing.netstandard2.0.cs +++ b/sdk/maps/Azure.Maps.Routing/api/Azure.Maps.Routing.netstandard2.0.cs @@ -42,6 +42,8 @@ public partial class MapsRoutingClient protected MapsRoutingClient() { } public MapsRoutingClient(Azure.AzureKeyCredential credential) { } public MapsRoutingClient(Azure.AzureKeyCredential credential, Azure.Maps.Routing.MapsRoutingClientOptions options) { } + public MapsRoutingClient(Azure.AzureSasCredential credential) { } + public MapsRoutingClient(Azure.AzureSasCredential credential, Azure.Maps.Routing.MapsRoutingClientOptions options) { } public MapsRoutingClient(Azure.Core.TokenCredential credential, string clientId) { } public MapsRoutingClient(Azure.Core.TokenCredential credential, string clientId, Azure.Maps.Routing.MapsRoutingClientOptions options) { } public virtual Azure.Response GetDirections(Azure.Maps.Routing.RouteDirectionQuery query, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } diff --git a/sdk/maps/Azure.Maps.Routing/samples/RouteDirectionsSamples.md b/sdk/maps/Azure.Maps.Routing/samples/RouteDirectionsSamples.md index dd1015a018124..00cf9999512fe 100644 --- a/sdk/maps/Azure.Maps.Routing/samples/RouteDirectionsSamples.md +++ b/sdk/maps/Azure.Maps.Routing/samples/RouteDirectionsSamples.md @@ -4,7 +4,7 @@ To use these samples, you'll first need to set up resources. See [getting starte ## Import the namespaces -```C# Snippet:RouteImportNamespace +```C# Snippet:RouteImportNamespaces using Azure.Core.GeoJson; using Azure.Maps.Routing; using Azure.Maps.Routing.Models; diff --git a/sdk/maps/Azure.Maps.Routing/samples/RouteMatrixSamples.md b/sdk/maps/Azure.Maps.Routing/samples/RouteMatrixSamples.md index de4a51883d432..17497430c9115 100644 --- a/sdk/maps/Azure.Maps.Routing/samples/RouteMatrixSamples.md +++ b/sdk/maps/Azure.Maps.Routing/samples/RouteMatrixSamples.md @@ -4,7 +4,7 @@ To use these samples, you'll first need to set up resources. See [getting starte ## Import the namespaces -```C# Snippet:RouteImportNamespace +```C# Snippet:RouteImportNamespaces using Azure.Core.GeoJson; using Azure.Maps.Routing; using Azure.Maps.Routing.Models; diff --git a/sdk/maps/Azure.Maps.Routing/samples/RouteRangeSamples.md b/sdk/maps/Azure.Maps.Routing/samples/RouteRangeSamples.md index 61a1ea93f829f..db72266044cde 100644 --- a/sdk/maps/Azure.Maps.Routing/samples/RouteRangeSamples.md +++ b/sdk/maps/Azure.Maps.Routing/samples/RouteRangeSamples.md @@ -4,7 +4,7 @@ To use these samples, you'll first need to set up resources. See [getting starte ## Import the namespaces -```C# Snippet:RouteImportNamespace +```C# Snippet:RouteImportNamespaces using Azure.Core.GeoJson; using Azure.Maps.Routing; using Azure.Maps.Routing.Models; diff --git a/sdk/maps/Azure.Maps.Routing/src/Azure.Maps.Routing.csproj b/sdk/maps/Azure.Maps.Routing/src/Azure.Maps.Routing.csproj index 5f9ded072439c..a2f9f9817aaaf 100644 --- a/sdk/maps/Azure.Maps.Routing/src/Azure.Maps.Routing.csproj +++ b/sdk/maps/Azure.Maps.Routing/src/Azure.Maps.Routing.csproj @@ -20,4 +20,8 @@ + + + + diff --git a/sdk/maps/Azure.Maps.Routing/src/MapsRoutingClient.cs b/sdk/maps/Azure.Maps.Routing/src/MapsRoutingClient.cs index 4dc04051deb13..5a8162fb1ceab 100644 --- a/sdk/maps/Azure.Maps.Routing/src/MapsRoutingClient.cs +++ b/sdk/maps/Azure.Maps.Routing/src/MapsRoutingClient.cs @@ -103,6 +103,35 @@ public MapsRoutingClient(TokenCredential credential, string clientId, MapsRoutin RestClient = new RouteRestClient(_clientDiagnostics, _pipeline, endpoint, clientId, options.Version); } + /// Initializes a new instance of MapsRoutingClient. + /// The Shared Access Signature credential used to connect to Azure. This signature + /// can be constructed using the . + public MapsRoutingClient(AzureSasCredential credential) + { + Argument.AssertNotNull(credential, nameof(credential)); + + var endpoint = new Uri("https://atlas.microsoft.com"); + var options = new MapsRoutingClientOptions(); + _clientDiagnostics = new ClientDiagnostics(options); + _pipeline = HttpPipelineBuilder.Build(options, new MapsSasCredentialPolicy(credential)); + RestClient = new RouteRestClient(_clientDiagnostics, _pipeline, endpoint, null, options.Version); + } + + /// Initializes a new instance of MapsRoutingClient. + /// The Shared Access Signature credential used to connect to Azure. This signature + /// can be constructed using the . + /// The options for configuring the client. + public MapsRoutingClient(AzureSasCredential credential, MapsRoutingClientOptions options) + { + Argument.AssertNotNull(credential, nameof(credential)); + + var endpoint = options.Endpoint; + options ??= new MapsRoutingClientOptions(); + _clientDiagnostics = new ClientDiagnostics(options); + _pipeline = HttpPipelineBuilder.Build(options, new MapsSasCredentialPolicy(credential)); + RestClient = new RouteRestClient(_clientDiagnostics, _pipeline, endpoint, null, options.Version); + } + /// /// The Matrix Routing service allows calculation of a matrix of route summaries for a set of routes defined by origin and destination locations by using an asynchronous (async) or synchronous (sync) request. /// For every given origin, the service calculates the cost of routing from that origin to every given destination. The set of origins and the set of destinations can be thought of as the column and row headers of a table and each cell in the table contains the costs of routing from the origin to the destination for that cell. As an example, let's say a food delivery company has 20 drivers and they need to find the closest driver to pick up the delivery from the restaurant. To solve this use case, they can call Matrix Route API. diff --git a/sdk/maps/Azure.Maps.Routing/tests/Azure.Maps.Routing.Tests.csproj b/sdk/maps/Azure.Maps.Routing/tests/Azure.Maps.Routing.Tests.csproj index c9b47e77ca049..199a02f8e22e8 100644 --- a/sdk/maps/Azure.Maps.Routing/tests/Azure.Maps.Routing.Tests.csproj +++ b/sdk/maps/Azure.Maps.Routing/tests/Azure.Maps.Routing.Tests.csproj @@ -9,6 +9,7 @@ + @@ -16,6 +17,7 @@ + diff --git a/sdk/maps/Azure.Maps.Routing/tests/Samples/RouteClientSamples.cs b/sdk/maps/Azure.Maps.Routing/tests/Samples/RouteClientSamples.cs index ce5f11bd58c49..d94df836d8261 100644 --- a/sdk/maps/Azure.Maps.Routing/tests/Samples/RouteClientSamples.cs +++ b/sdk/maps/Azure.Maps.Routing/tests/Samples/RouteClientSamples.cs @@ -4,14 +4,19 @@ using System; using System.Collections.Generic; using System.Threading; -using Azure.Core; -#region Snippet:RouteImportNamespace +#region Snippet:RouteImportNamespaces using Azure.Core.GeoJson; using Azure.Maps.Routing; using Azure.Maps.Routing.Models; #endregion using Azure.Core.TestFramework; using NUnit.Framework; +#region Snippet:RouteSasAuthImportNamespaces +using Azure.Core; +using Azure.ResourceManager; +using Azure.ResourceManager.Maps; +using Azure.ResourceManager.Maps.Models; +#endregion namespace Azure.Maps.Routing.Tests { @@ -41,6 +46,41 @@ public void RouteClientViaSubscriptionKey() #endregion } + public void RouteClientViaSas() + { + #region Snippet:InstantiateRouteClientViaSas + // Get your azure access token, for more details of how Azure SDK get your access token, please refer to https://learn.microsoft.com/en-us/dotnet/azure/sdk/authentication?tabs=command-line + TokenCredential cred = new DefaultAzureCredential(); + // Authenticate your client + ArmClient armClient = new ArmClient(cred); + + string subscriptionId = "MyMapsSubscriptionId"; + string resourceGroupName = "MyMapsResourceGroupName"; + string accountName = "MyMapsAccountName"; + + // Get maps account resource + ResourceIdentifier mapsAccountResourceId = MapsAccountResource.CreateResourceIdentifier(subscriptionId, resourceGroupName, accountName); + MapsAccountResource mapsAccount = armClient.GetMapsAccountResource(mapsAccountResourceId); + + // Assign SAS token information + // Every time you want to SAS token, update the principal ID, max rate, start and expiry time + string principalId = "MyManagedIdentityObjectId"; + int maxRatePerSecond = 500; + + // Set start and expiry time for the SAS token in round-trip date/time format + DateTime now = DateTime.Now; + string start = now.ToString("O"); + string expiry = now.AddDays(1).ToString("O"); + + MapsAccountSasContent sasContent = new MapsAccountSasContent(MapsSigningKey.PrimaryKey, principalId, maxRatePerSecond, start, expiry); + Response sas = mapsAccount.GetSas(sasContent); + + // Create a SearchClient that will authenticate via SAS token + AzureSasCredential sasCredential = new AzureSasCredential(sas.Value.AccountSasToken); + MapsRoutingClient client = new MapsRoutingClient(sasCredential); + #endregion + } + [Test] public void GetRouteDirections() { From af3aeaa6fc4db042cf39d9fdd6f29c7503f9a5a7 Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Tue, 4 Jul 2023 00:14:27 +0800 Subject: [PATCH 20/21] Update API interface --- .../api/Azure.Maps.Common.netstandard2.0.cs | 5 ----- .../api/Azure.Maps.Rendering.netstandard2.0.cs | 2 ++ 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/sdk/maps/Azure.Maps.Common/api/Azure.Maps.Common.netstandard2.0.cs b/sdk/maps/Azure.Maps.Common/api/Azure.Maps.Common.netstandard2.0.cs index 19f5041538b1a..ed44597cbf784 100644 --- a/sdk/maps/Azure.Maps.Common/api/Azure.Maps.Common.netstandard2.0.cs +++ b/sdk/maps/Azure.Maps.Common/api/Azure.Maps.Common.netstandard2.0.cs @@ -34,9 +34,4 @@ namespace Azure.Maps public static bool operator !=(Azure.Maps.LocalizedMapView left, Azure.Maps.LocalizedMapView right) { throw null; } public override string ToString() { throw null; } } - public partial class MapsSasCredentialPolicy : Azure.Core.Pipeline.HttpPipelineSynchronousPolicy - { - public MapsSasCredentialPolicy(Azure.AzureSasCredential credential) { } - public override void OnSendingRequest(Azure.Core.HttpMessage message) { } - } } diff --git a/sdk/maps/Azure.Maps.Rendering/api/Azure.Maps.Rendering.netstandard2.0.cs b/sdk/maps/Azure.Maps.Rendering/api/Azure.Maps.Rendering.netstandard2.0.cs index 0b0569d1b5fc5..42da99e83a3cf 100644 --- a/sdk/maps/Azure.Maps.Rendering/api/Azure.Maps.Rendering.netstandard2.0.cs +++ b/sdk/maps/Azure.Maps.Rendering/api/Azure.Maps.Rendering.netstandard2.0.cs @@ -96,6 +96,8 @@ public partial class MapsRenderingClient protected MapsRenderingClient() { } public MapsRenderingClient(Azure.AzureKeyCredential credential) { } public MapsRenderingClient(Azure.AzureKeyCredential credential, Azure.Maps.Rendering.MapsRenderingClientOptions options) { } + public MapsRenderingClient(Azure.AzureSasCredential credential) { } + public MapsRenderingClient(Azure.AzureSasCredential credential, Azure.Maps.Rendering.MapsRenderingClientOptions options) { } public MapsRenderingClient(Azure.Core.TokenCredential credential, string clientId) { } public MapsRenderingClient(Azure.Core.TokenCredential credential, string clientId, Azure.Maps.Rendering.MapsRenderingClientOptions options) { } public virtual Azure.Response GetCopyrightCaption(System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) { throw null; } From 28fad46def11a8c0c7a03398b423af70a8db3c08 Mon Sep 17 00:00:00 2001 From: Charlie Chen Date: Tue, 4 Jul 2023 00:16:00 +0800 Subject: [PATCH 21/21] Fix typos --- sdk/maps/Azure.Maps.Search/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/maps/Azure.Maps.Search/README.md b/sdk/maps/Azure.Maps.Search/README.md index 72cb015247967..d96f0f91b96ed 100644 --- a/sdk/maps/Azure.Maps.Search/README.md +++ b/sdk/maps/Azure.Maps.Search/README.md @@ -67,7 +67,7 @@ dotnet add package Azure.ResourceManager.Maps --prerelease In the code, we need to import the following lines for both Azure Maps SDK and ResourceManager: -```C# Snippet:RenderImportNamespaces +```C# Snippet:SearchImportNamespaces using Azure.Core.GeoJson; using Azure.Maps.Search; using Azure.Maps.Search.Models;