diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/CHANGELOG.md b/sdk/keyvault/Azure.Security.KeyVault.Administration/CHANGELOG.md index 164def70f2b6..9ff8de562942 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/CHANGELOG.md +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 4.2.0-beta.1 (Unreleased) +## 4.3.0-beta.1 (Unreleased) ### Features Added @@ -10,6 +10,14 @@ ### Other Changes +## 4.2.0 (2022-09-20) + +### Breaking Changes + +- Verify the challenge resource matches the vault domain. + This should affect few customers who can set `KeyVaultAdministrationClientOptions.DisableChallengeResourceVerification` to `true` to disable. + See https://aka.ms/azsdk/blog/vault-uri for more information. + ## 4.1.0 (2022-03-24) Changes from both the last release and the last beta include: @@ -88,7 +96,7 @@ Changes from both the last release and the last beta include: - Refactor `RestoreOperation` to return `RestoreResult` - Renamed `KeyVaultPermissions` Not\* properties to Deny\* - Renamed `KeyVaultRoleAssignment` `Type` property to `RoleAssignmentType` -- Made `KeyVaultRoleAssignmentProperties` internal and moved its properties to method parameters for `CreateRoleAssignment` +- Made `KeyVaultRoleAssignmentProperties` internal and moved its properties to method parameters for `CreateRoleAssignment` ## 4.0.0-beta.2 (2020-10-06) diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/api/Azure.Security.KeyVault.Administration.netstandard2.0.cs b/sdk/keyvault/Azure.Security.KeyVault.Administration/api/Azure.Security.KeyVault.Administration.netstandard2.0.cs index d6c76260777a..bb6a7eb27316 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/api/Azure.Security.KeyVault.Administration.netstandard2.0.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/api/Azure.Security.KeyVault.Administration.netstandard2.0.cs @@ -39,6 +39,7 @@ public KeyVaultAccessControlClient(System.Uri vaultUri, Azure.Core.TokenCredenti public partial class KeyVaultAdministrationClientOptions : Azure.Core.ClientOptions { public KeyVaultAdministrationClientOptions(Azure.Security.KeyVault.Administration.KeyVaultAdministrationClientOptions.ServiceVersion version = Azure.Security.KeyVault.Administration.KeyVaultAdministrationClientOptions.ServiceVersion.V7_3) { } + public bool DisableChallengeResourceVerification { get { throw null; } set { } } public Azure.Security.KeyVault.Administration.KeyVaultAdministrationClientOptions.ServiceVersion Version { get { throw null; } } public enum ServiceVersion { diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/Azure.Security.KeyVault.Administration.csproj b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/Azure.Security.KeyVault.Administration.csproj index 9180db0904e2..5b4dff902346 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/Azure.Security.KeyVault.Administration.csproj +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/Azure.Security.KeyVault.Administration.csproj @@ -3,9 +3,9 @@ This is the Microsoft Azure Key Vault Administration client library Microsoft Azure.Security.KeyVault.Administration client library - 4.2.0-beta.1 + 4.3.0-beta.1 - 4.1.0 + 4.2.0 Microsoft Azure Key Vault Administration;$(PackageCommonTags) $(RequiredTargetFrameworks) $(NoWarn);3021;CA1812 diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultAccessControlClient.cs b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultAccessControlClient.cs index da9682685a30..2f2591c00e32 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultAccessControlClient.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultAccessControlClient.cs @@ -36,7 +36,7 @@ protected KeyVaultAccessControlClient() /// /// Initializes a new instance of the class for the specified vault. /// - /// A to the vault on which the client operates. Appears as "DNS Name" in the Azure portal. + /// A to the vault on which the client operates. Appears as "DNS Name" in the Azure portal. You should validate that this URI references a valid Key Vault or Managed HSM resource. See https://aka.ms/azsdk/blog/vault-uri for details. /// A used to authenticate requests to the vault, such as DefaultAzureCredential. /// or is null. public KeyVaultAccessControlClient(Uri vaultUri, TokenCredential credential) @@ -47,7 +47,7 @@ public KeyVaultAccessControlClient(Uri vaultUri, TokenCredential credential) /// /// Initializes a new instance of the class for the specified vault. /// - /// A to the vault on which the client operates. Appears as "DNS Name" in the Azure portal. + /// A to the vault on which the client operates. Appears as "DNS Name" in the Azure portal. You should validate that this URI references a valid Key Vault or Managed HSM resource. See https://aka.ms/azsdk/blog/vault-uri for details. /// A used to authenticate requests to the vault, such as DefaultAzureCredential. /// that allow to configure the management of the request sent to Key Vault. /// or is null. @@ -62,7 +62,7 @@ public KeyVaultAccessControlClient(Uri vaultUri, TokenCredential credential, Key string apiVersion = options.GetVersionString(); HttpPipeline pipeline = HttpPipelineBuilder.Build(options, - new ChallengeBasedAuthenticationPolicy(credential)); + new ChallengeBasedAuthenticationPolicy(credential, options.DisableChallengeResourceVerification)); _diagnostics = new ClientDiagnostics(options); _definitionsRestClient = new RoleDefinitionsRestClient(_diagnostics, pipeline, apiVersion); diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultAdministrationClientOptions.cs b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultAdministrationClientOptions.cs index 2c2336006d89..bb21d7149e07 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultAdministrationClientOptions.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultAdministrationClientOptions.cs @@ -59,6 +59,11 @@ public KeyVaultAdministrationClientOptions(ServiceVersion version = LatestVersio this.ConfigureLogging(); } + /// + /// Gets or sets whether to disable verification that the authentication challenge resource matches the Key Vault or Managed HSM domain. + /// + public bool DisableChallengeResourceVerification { get; set; } + internal string GetVersionString() { return Version switch diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultBackupClient.cs b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultBackupClient.cs index e5d94a2d0a7c..6779fb3fcfa4 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultBackupClient.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/src/KeyVaultBackupClient.cs @@ -33,7 +33,7 @@ protected KeyVaultBackupClient() /// /// Initializes a new instance of the class for the specified vault. /// - /// A to the vault on which the client operates. Appears as "DNS Name" in the Azure portal. + /// A to the vault on which the client operates. Appears as "DNS Name" in the Azure portal. You should validate that this URI references a valid Key Vault or Managed HSM resource. See https://aka.ms/azsdk/blog/vault-uri for details. /// A used to authenticate requests to the vault, such as DefaultAzureCredential. /// or is null. public KeyVaultBackupClient(Uri vaultUri, TokenCredential credential) @@ -43,7 +43,7 @@ public KeyVaultBackupClient(Uri vaultUri, TokenCredential credential) /// /// Initializes a new instance of the class for the specified vault. /// - /// A to the vault on which the client operates. Appears as "DNS Name" in the Azure portal. + /// A to the vault on which the client operates. Appears as "DNS Name" in the Azure portal You should validate that this URI references a valid Key Vault or Managed HSM resource. See https://aka.ms/azsdk/blog/vault-uri for details.. /// A used to authenticate requests to the vault, such as DefaultAzureCredential. /// that allow to configure the management of the request sent to Key Vault. /// or is null. @@ -58,7 +58,7 @@ public KeyVaultBackupClient(Uri vaultUri, TokenCredential credential, KeyVaultAd string apiVersion = options.GetVersionString(); HttpPipeline pipeline = HttpPipelineBuilder.Build(options, - new ChallengeBasedAuthenticationPolicy(credential)); + new ChallengeBasedAuthenticationPolicy(credential, options.DisableChallengeResourceVerification)); _diagnostics = new ClientDiagnostics(options); _restClient = new BackupRestoreRestClient(_diagnostics, pipeline, apiVersion); diff --git a/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/ChallengeBasedAuthenticationPolicyTests.cs b/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/ChallengeBasedAuthenticationPolicyTests.cs index d4b005d6dee4..30f406117ac9 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/ChallengeBasedAuthenticationPolicyTests.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Administration/tests/ChallengeBasedAuthenticationPolicyTests.cs @@ -2,6 +2,8 @@ // Licensed under the MIT License. using System; +using System.Collections.Generic; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Azure.Core; @@ -10,39 +12,85 @@ namespace Azure.Security.KeyVault.Tests { + [NonParallelizable] public class ChallengeBasedAuthenticationPolicyTests : SyncAsyncPolicyTestBase { internal ChallengeBasedAuthenticationPolicy _policy; private const string KeyVaultChallenge = "Bearer authorization=\"https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47\", resource=\"https://vault.azure.net\""; public ChallengeBasedAuthenticationPolicyTests(bool isAsync) : base(isAsync) { - _policy = new ChallengeBasedAuthenticationPolicy(new MockCredentialThrowsWithNoScopes()); + _policy = new ChallengeBasedAuthenticationPolicy(new MockCredentialThrowsWithNoScopes(), false); } - [Test] - [NonParallelizable] - public async Task ScopesAreInitializedFromCache() + [SetUp] + public void SetUp() { // Clear the cache to ensure the test starts with an empty cache. ChallengeBasedAuthenticationPolicy.ClearCache(); + } + [Test] + public async Task ScopesAreInitializedFromCache() + { var keyvaultChallengeResponse = new MockResponse(401); keyvaultChallengeResponse.AddHeader(new HttpHeader("WWW-Authenticate", KeyVaultChallenge)); MockTransport transport = CreateMockTransport(keyvaultChallengeResponse, new MockResponse(200)); - var response = await SendGetRequest(transport, _policy, uri: new Uri("https://example.com")); + Response response = await SendGetRequest(transport, _policy, uri: new Uri("https://myvault.vault.azure.net")); Assert.That(response.Status, Is.EqualTo(200)); // Construct a new policy so that we can get the Scopes from cache. - _policy = new ChallengeBasedAuthenticationPolicy(new MockCredentialThrowsWithNoScopes()); + _policy = new ChallengeBasedAuthenticationPolicy(new MockCredentialThrowsWithNoScopes(), false); - transport = CreateMockTransport(keyvaultChallengeResponse, new MockResponse(200)); - response = await SendGetRequest(transport, _policy, uri: new Uri("https://example.com")); + transport = CreateMockTransport(new MockResponse(200)); + response = await SendGetRequest(transport, _policy, uri: new Uri("https://myvault.vault.azure.net")); Assert.That(response.Status, Is.EqualTo(200)); } + [TestCaseSource(nameof(VerifyChallengeResourceData))] + public async Task VerifyChallengeResource(Uri uri, bool disableVerification) + { + var keyvaultChallengeResponse = new MockResponse(401); + keyvaultChallengeResponse.AddHeader(new HttpHeader("WWW-Authenticate", KeyVaultChallenge)); + MockTransport transport = CreateMockTransport(keyvaultChallengeResponse, new MockResponse(200)); + + ChallengeBasedAuthenticationPolicy policy = new(new MockCredentialThrowsWithNoScopes(), disableVerification); + + if (!disableVerification) + { + InvalidOperationException ex = Assert.ThrowsAsync(async () => await SendGetRequest(transport, policy, uri: uri)); + Assert.That(ex.Message, Is.EqualTo("The challenge resource 'vault.azure.net' does not match the requested domain. Set DisableChallengeResourceVerification to true in your client options to disable. See https://aka.ms/azsdk/blog/vault-uri for more information.")); + } + else + { + Response response = await SendGetRequest(transport, policy, uri: uri); + Assert.That(response.Status, Is.EqualTo(200)); + } + } + + private static IEnumerable VerifyChallengeResourceData => new[] + { + "https://example.com", + "https://examplevault.azure.net", + "https://example.vault.azure.com", + }.Zip(new[] { false, true }, (uri, disableVerification) => new object[] { new Uri(uri), disableVerification }); + + [Test] + public void VerifyChallengeResourceInvalidUri() + { + var keyvaultChallengeResponse = new MockResponse(401); + keyvaultChallengeResponse.AddHeader(new HttpHeader("WWW-Authenticate", "Bearer authorization=\"https://login.microsoftonline.com/72f988bf-86f1-41af-91ab-2d7cd011db47\", resource=\"invalid-uri\"")); + MockTransport transport = CreateMockTransport(keyvaultChallengeResponse, new MockResponse(200)); + + ChallengeBasedAuthenticationPolicy policy = new(new MockCredentialThrowsWithNoScopes(), false); + Uri uri = new("https://example.com"); + + InvalidOperationException ex = Assert.ThrowsAsync(async () => await SendGetRequest(transport, policy, uri: uri)); + Assert.That(ex.Message, Is.EqualTo("The challenge contains invalid scope 'invalid-uri/.default'.")); + } + public class MockCredentialThrowsWithNoScopes : TokenCredential { public override ValueTask GetTokenAsync(TokenRequestContext requestContext, CancellationToken cancellationToken) diff --git a/sdk/keyvault/Azure.Security.KeyVault.Certificates/CHANGELOG.md b/sdk/keyvault/Azure.Security.KeyVault.Certificates/CHANGELOG.md index 915da2137bca..5f4e43b7751a 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Certificates/CHANGELOG.md +++ b/sdk/keyvault/Azure.Security.KeyVault.Certificates/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 4.4.0-beta.1 (Unreleased) +## 4.5.0-beta.1 (Unreleased) ### Features Added @@ -10,6 +10,14 @@ ### Other Changes +## 4.4.0 (2022-09-20) + +### Breaking Changes + +- Verify the challenge resource matches the vault domain. + This should affect few customers who can set `CertificateClientOptions.DisableChallengeResourceVerification` to `true` to disable. + See https://aka.ms/azsdk/blog/vault-uri for more information. + ## 4.3.0 (2022-03-24) Changes from both the last release and the last beta include: diff --git a/sdk/keyvault/Azure.Security.KeyVault.Certificates/api/Azure.Security.KeyVault.Certificates.netstandard2.0.cs b/sdk/keyvault/Azure.Security.KeyVault.Certificates/api/Azure.Security.KeyVault.Certificates.netstandard2.0.cs index 6a2be436387d..d008cfed082f 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Certificates/api/Azure.Security.KeyVault.Certificates.netstandard2.0.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Certificates/api/Azure.Security.KeyVault.Certificates.netstandard2.0.cs @@ -74,6 +74,7 @@ public CertificateClient(System.Uri vaultUri, Azure.Core.TokenCredential credent public partial class CertificateClientOptions : Azure.Core.ClientOptions { public CertificateClientOptions(Azure.Security.KeyVault.Certificates.CertificateClientOptions.ServiceVersion version = Azure.Security.KeyVault.Certificates.CertificateClientOptions.ServiceVersion.V7_3) { } + public bool DisableChallengeResourceVerification { get { throw null; } set { } } public Azure.Security.KeyVault.Certificates.CertificateClientOptions.ServiceVersion Version { get { throw null; } } public enum ServiceVersion { diff --git a/sdk/keyvault/Azure.Security.KeyVault.Certificates/src/Azure.Security.KeyVault.Certificates.csproj b/sdk/keyvault/Azure.Security.KeyVault.Certificates/src/Azure.Security.KeyVault.Certificates.csproj index 268cc184c3c9..ed1692b1d346 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Certificates/src/Azure.Security.KeyVault.Certificates.csproj +++ b/sdk/keyvault/Azure.Security.KeyVault.Certificates/src/Azure.Security.KeyVault.Certificates.csproj @@ -3,9 +3,9 @@ This is the Microsoft Azure Key Vault Certificates client library Microsoft Azure.Security.KeyVault.Certificates client library - 4.4.0-beta.1 + 4.5.0-beta.1 - 4.3.0 + 4.4.0 Microsoft Azure Key Vault Certificates;$(PackageCommonTags) $(RequiredTargetFrameworks) $(NoWarn);3021 diff --git a/sdk/keyvault/Azure.Security.KeyVault.Certificates/src/CertificateClient.cs b/sdk/keyvault/Azure.Security.KeyVault.Certificates/src/CertificateClient.cs index 543813228424..9eced2f996d6 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Certificates/src/CertificateClient.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Certificates/src/CertificateClient.cs @@ -42,6 +42,7 @@ protected CertificateClient() /// /// A to the vault on which the client operates. Appears as "DNS Name" in the Azure portal. /// If you have a certificate , use to parse the and other information. + /// You should validate that this URI references a valid Key Vault resource. See https://aka.ms/azsdk/blog/vault-uri for details. /// /// A used to authenticate requests to the vault, such as DefaultAzureCredential. /// or is null. @@ -56,6 +57,7 @@ public CertificateClient(Uri vaultUri, TokenCredential credential) /// /// A to the vault on which the client operates. Appears as "DNS Name" in the Azure portal. /// If you have a certificate , use to parse the and other information. + /// You should validate that this URI references a valid Key Vault resource. See https://aka.ms/azsdk/blog/vault-uri for details. /// /// A used to authenticate requests to the vault, such as DefaultAzureCredential. /// that allow to configure the management of the request sent to Key Vault. @@ -67,7 +69,7 @@ public CertificateClient(Uri vaultUri, TokenCredential credential, CertificateCl options ??= new CertificateClientOptions(); - HttpPipeline pipeline = HttpPipelineBuilder.Build(options, new ChallengeBasedAuthenticationPolicy(credential)); + HttpPipeline pipeline = HttpPipelineBuilder.Build(options, new ChallengeBasedAuthenticationPolicy(credential, options.DisableChallengeResourceVerification)); _pipeline = new KeyVaultPipeline(vaultUri, options.GetVersionString(), pipeline, new ClientDiagnostics(options)); } diff --git a/sdk/keyvault/Azure.Security.KeyVault.Certificates/src/CertificateClientOptions.cs b/sdk/keyvault/Azure.Security.KeyVault.Certificates/src/CertificateClientOptions.cs index b80b300ab24b..0e5c6b5e07ff 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Certificates/src/CertificateClientOptions.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Certificates/src/CertificateClientOptions.cs @@ -69,6 +69,11 @@ public CertificateClientOptions(ServiceVersion version = LatestVersion) this.ConfigureLogging(); } + /// + /// Gets or sets whether to disable verification that the authentication challenge resource matches the Key Vault domain. + /// + public bool DisableChallengeResourceVerification { get; set; } + internal string GetVersionString() { return Version switch diff --git a/sdk/keyvault/Azure.Security.KeyVault.Keys/CHANGELOG.md b/sdk/keyvault/Azure.Security.KeyVault.Keys/CHANGELOG.md index b394169fe4f7..4f8e9fa7797a 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Keys/CHANGELOG.md +++ b/sdk/keyvault/Azure.Security.KeyVault.Keys/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 4.4.0-beta.1 (Unreleased) +## 4.5.0-beta.1 (Unreleased) ### Features Added @@ -10,6 +10,14 @@ ### Other Changes +## 4.4.0 (2022-09-20) + +### Breaking Changes + +- Verify the challenge resource matches the vault domain. + This should affect few customers who can set `KeyClientOptions.DisableChallengeResourceVerification` or `CryptographyClientOptions.DisableChallengeResourceVerification` to `true` to disable. + See https://aka.ms/azsdk/blog/vault-uri for more information. + ## 4.3.0 (2022-03-24) Changes from both the last release and the last beta include: diff --git a/sdk/keyvault/Azure.Security.KeyVault.Keys/api/Azure.Security.KeyVault.Keys.netstandard2.0.cs b/sdk/keyvault/Azure.Security.KeyVault.Keys/api/Azure.Security.KeyVault.Keys.netstandard2.0.cs index 64bba60ea245..73aa5af85595 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Keys/api/Azure.Security.KeyVault.Keys.netstandard2.0.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Keys/api/Azure.Security.KeyVault.Keys.netstandard2.0.cs @@ -160,6 +160,7 @@ public KeyClient(System.Uri vaultUri, Azure.Core.TokenCredential credential, Azu public partial class KeyClientOptions : Azure.Core.ClientOptions { public KeyClientOptions(Azure.Security.KeyVault.Keys.KeyClientOptions.ServiceVersion version = Azure.Security.KeyVault.Keys.KeyClientOptions.ServiceVersion.V7_3) { } + public bool DisableChallengeResourceVerification { get { throw null; } set { } } public Azure.Security.KeyVault.Keys.KeyClientOptions.ServiceVersion Version { get { throw null; } } public enum ServiceVersion { @@ -424,6 +425,7 @@ public CryptographyClient(System.Uri keyId, Azure.Core.TokenCredential credentia public partial class CryptographyClientOptions : Azure.Core.ClientOptions { public CryptographyClientOptions(Azure.Security.KeyVault.Keys.Cryptography.CryptographyClientOptions.ServiceVersion version = Azure.Security.KeyVault.Keys.Cryptography.CryptographyClientOptions.ServiceVersion.V7_3) { } + public bool DisableChallengeResourceVerification { get { throw null; } set { } } public Azure.Security.KeyVault.Keys.Cryptography.CryptographyClientOptions.ServiceVersion Version { get { throw null; } } public enum ServiceVersion { diff --git a/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Azure.Security.KeyVault.Keys.csproj b/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Azure.Security.KeyVault.Keys.csproj index 03cda41b3d6f..b084acb2a0b5 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Azure.Security.KeyVault.Keys.csproj +++ b/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Azure.Security.KeyVault.Keys.csproj @@ -3,9 +3,9 @@ This is the Microsoft Azure Key Vault Keys client library Microsoft Azure.Security.KeyVault.Keys client library - 4.4.0-beta.1 + 4.5.0-beta.1 - 4.3.0 + 4.4.0 Microsoft Azure Key Vault Keys;$(PackageCommonTags) $(RequiredTargetFrameworks) diff --git a/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Cryptography/CryptographyClient.cs b/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Cryptography/CryptographyClient.cs index fdf864a43351..cde697bb6a76 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Cryptography/CryptographyClient.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Cryptography/CryptographyClient.cs @@ -36,6 +36,7 @@ protected CryptographyClient() /// /// The key identifier of the which will be used for cryptographic operations. /// If you have a key , use to parse the and other information. + /// You should validate that this URI references a valid Key Vault or Managed HSM resource. See https://aka.ms/azsdk/blog/vault-uri for details. /// /// A used to authenticate requests to the vault, like DefaultAzureCredential. /// or is null. @@ -50,6 +51,7 @@ public CryptographyClient(Uri keyId, TokenCredential credential) /// /// The key identifier of the which will be used for cryptographic operations. /// If you have a key , use to parse the and other information. + /// You should validate that this URI references a valid Key Vault or Managed HSM resource. See https://aka.ms/azsdk/blog/vault-uri for details. /// /// A used to authenticate requests to the vault, like DefaultAzureCredential. /// the for local or remote operations on Key Vault. diff --git a/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Cryptography/CryptographyClientOptions.cs b/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Cryptography/CryptographyClientOptions.cs index 9f190351d241..d2e7fc5370a3 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Cryptography/CryptographyClientOptions.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Cryptography/CryptographyClientOptions.cs @@ -69,6 +69,11 @@ public CryptographyClientOptions(ServiceVersion version = LatestVersion) this.ConfigureLogging(); } + /// + /// Gets or sets whether to disable verification that the authentication challenge resource matches the Key Vault or Managed HSM domain. + /// + public bool DisableChallengeResourceVerification { get; set; } + internal string GetVersionString() { return Version switch diff --git a/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Cryptography/KeyResolver.cs b/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Cryptography/KeyResolver.cs index cfcebf660a73..f906722eebd2 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Cryptography/KeyResolver.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Cryptography/KeyResolver.cs @@ -56,7 +56,7 @@ public KeyResolver(TokenCredential credential, CryptographyClientOptions options _apiVersion = options.GetVersionString(); _pipeline = HttpPipelineBuilder.Build(options, - new ChallengeBasedAuthenticationPolicy(credential)); + new ChallengeBasedAuthenticationPolicy(credential, options.DisableChallengeResourceVerification)); _clientDiagnostics = new ClientDiagnostics(options); } @@ -64,7 +64,7 @@ public KeyResolver(TokenCredential credential, CryptographyClientOptions options /// /// Retrieves a capable of performing cryptographic operations with the key represented by the specified . /// - /// The key identifier of the key used by the created . + /// The key identifier of the key used by the created . You should validate that this URI references a valid Key Vault or Managed HSM resource. See https://aka.ms/azsdk/blog/vault-uri for details. /// A controlling the request lifetime. /// A new capable of performing cryptographic operations with the key represented by the specified . /// is null. diff --git a/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Cryptography/RemoteCryptographyClient.cs b/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Cryptography/RemoteCryptographyClient.cs index f40099f6a7a1..b49fe8e8268f 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Cryptography/RemoteCryptographyClient.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Keys/src/Cryptography/RemoteCryptographyClient.cs @@ -27,7 +27,7 @@ internal RemoteCryptographyClient(Uri keyId, TokenCredential credential, Cryptog string apiVersion = options.GetVersionString(); HttpPipeline pipeline = HttpPipelineBuilder.Build(options, - new ChallengeBasedAuthenticationPolicy(credential)); + new ChallengeBasedAuthenticationPolicy(credential, options.DisableChallengeResourceVerification)); Pipeline = new KeyVaultPipeline(keyId, apiVersion, pipeline, new ClientDiagnostics(options)); } diff --git a/sdk/keyvault/Azure.Security.KeyVault.Keys/src/KeyClient.cs b/sdk/keyvault/Azure.Security.KeyVault.Keys/src/KeyClient.cs index b421bed3ea38..b10c97cc6bb0 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Keys/src/KeyClient.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Keys/src/KeyClient.cs @@ -39,6 +39,7 @@ protected KeyClient() /// /// A to the vault on which the client operates. Appears as "DNS Name" in the Azure portal. /// If you have a key , use to parse the and other information. + /// You should validate that this URI references a valid Key Vault or Managed HSM resource. See https://aka.ms/azsdk/blog/vault-uri for details. /// /// A used to authenticate requests to the vault, such as DefaultAzureCredential. /// or is null. @@ -53,6 +54,7 @@ public KeyClient(Uri vaultUri, TokenCredential credential) /// /// A to the vault on which the client operates. Appears as "DNS Name" in the Azure portal. /// If you have a key , use to parse the and other information. + /// You should validate that this URI references a valid Key Vault or Managed HSM resource. See https://aka.ms/azsdk/blog/vault-uri for details. /// /// A used to authenticate requests to the vault, such as DefaultAzureCredential. /// that allow to configure the management of the request sent to Key Vault. @@ -66,7 +68,7 @@ public KeyClient(Uri vaultUri, TokenCredential credential, KeyClientOptions opti string apiVersion = options.GetVersionString(); HttpPipeline pipeline = HttpPipelineBuilder.Build(options, - new ChallengeBasedAuthenticationPolicy(credential)); + new ChallengeBasedAuthenticationPolicy(credential, options.DisableChallengeResourceVerification)); _clientDiagnostics = new ClientDiagnostics(options); _pipeline = new KeyVaultPipeline(vaultUri, apiVersion, pipeline, _clientDiagnostics); diff --git a/sdk/keyvault/Azure.Security.KeyVault.Keys/src/KeyClientOptions.cs b/sdk/keyvault/Azure.Security.KeyVault.Keys/src/KeyClientOptions.cs index 7693b6cc2fb6..7bbda8b0154a 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Keys/src/KeyClientOptions.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Keys/src/KeyClientOptions.cs @@ -69,6 +69,11 @@ public KeyClientOptions(ServiceVersion version = LatestVersion) this.ConfigureLogging(); } + /// + /// Gets or sets whether to disable verification that the authentication challenge resource matches the Key Vault or Managed HSM domain. + /// + public bool DisableChallengeResourceVerification { get; set; } + internal string GetVersionString() { return Version switch diff --git a/sdk/keyvault/Azure.Security.KeyVault.Secrets/CHANGELOG.md b/sdk/keyvault/Azure.Security.KeyVault.Secrets/CHANGELOG.md index ffa7e50809ce..965a32e901d3 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Secrets/CHANGELOG.md +++ b/sdk/keyvault/Azure.Security.KeyVault.Secrets/CHANGELOG.md @@ -1,6 +1,6 @@ # Release History -## 4.4.0-beta.1 (Unreleased) +## 4.5.0-beta.1 (Unreleased) ### Features Added @@ -10,6 +10,14 @@ ### Other Changes +## 4.4.0 (2022-09-20) + +### Breaking Changes + +- Verify the challenge resource matches the vault domain. + This should affect few customers who can set `SecretClientOptions.DisableChallengeResourceVerification` to `true` to disable. + See https://aka.ms/azsdk/blog/vault-uri for more information. + ## 4.3.0 (2022-03-24) Changes from both the last release and the last beta include: diff --git a/sdk/keyvault/Azure.Security.KeyVault.Secrets/api/Azure.Security.KeyVault.Secrets.netstandard2.0.cs b/sdk/keyvault/Azure.Security.KeyVault.Secrets/api/Azure.Security.KeyVault.Secrets.netstandard2.0.cs index 241d36ee3b3a..19f3723b27ab 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Secrets/api/Azure.Security.KeyVault.Secrets.netstandard2.0.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Secrets/api/Azure.Security.KeyVault.Secrets.netstandard2.0.cs @@ -96,6 +96,7 @@ public SecretClient(System.Uri vaultUri, Azure.Core.TokenCredential credential, public partial class SecretClientOptions : Azure.Core.ClientOptions { public SecretClientOptions(Azure.Security.KeyVault.Secrets.SecretClientOptions.ServiceVersion version = Azure.Security.KeyVault.Secrets.SecretClientOptions.ServiceVersion.V7_3) { } + public bool DisableChallengeResourceVerification { get { throw null; } set { } } public Azure.Security.KeyVault.Secrets.SecretClientOptions.ServiceVersion Version { get { throw null; } } public enum ServiceVersion { diff --git a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/Azure.Security.KeyVault.Secrets.csproj b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/Azure.Security.KeyVault.Secrets.csproj index d06f41ab612c..6bd62d5a5082 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/Azure.Security.KeyVault.Secrets.csproj +++ b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/Azure.Security.KeyVault.Secrets.csproj @@ -3,9 +3,9 @@ This is the Microsoft Azure Key Vault Secrets client library Microsoft Azure.Security.KeyVault.Secrets client library - 4.4.0-beta.1 + 4.5.0-beta.1 - 4.3.0 + 4.4.0 Microsoft Azure Key Vault Secrets;$(PackageCommonTags) $(RequiredTargetFrameworks) @@ -22,7 +22,7 @@ - + diff --git a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClient.cs b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClient.cs index 88cc54903c65..4b9150089f72 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClient.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClient.cs @@ -34,6 +34,7 @@ protected SecretClient() /// /// A to the vault on which the client operates. Appears as "DNS Name" in the Azure portal. /// If you have a secret , use to parse the and other information. + /// You should validate that this URI references a valid Key Vault resource. See https://aka.ms/azsdk/blog/vault-uri for details. /// /// A used to authenticate requests to the vault, such as DefaultAzureCredential. /// or is null. @@ -48,6 +49,7 @@ public SecretClient(Uri vaultUri, TokenCredential credential) /// /// A to the vault on which the client operates. Appears as "DNS Name" in the Azure portal. /// If you have a secret , use to parse the and other information. + /// You should validate that this URI references a valid Key Vault resource. See https://aka.ms/azsdk/blog/vault-uri for details. /// /// A used to authenticate requests to the vault, such as DefaultAzureCredential. /// that allow to configure the management of the request sent to Key Vault. @@ -61,7 +63,7 @@ public SecretClient(Uri vaultUri, TokenCredential credential, SecretClientOption string apiVersion = options.GetVersionString(); HttpPipeline pipeline = HttpPipelineBuilder.Build(options, - new ChallengeBasedAuthenticationPolicy(credential)); + new ChallengeBasedAuthenticationPolicy(credential, options.DisableChallengeResourceVerification)); _pipeline = new KeyVaultPipeline(vaultUri, apiVersion, pipeline, new ClientDiagnostics(options)); } diff --git a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientOptions.cs b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientOptions.cs index d48c09d66772..36a29c288d46 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientOptions.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Secrets/src/SecretClientOptions.cs @@ -69,6 +69,11 @@ public SecretClientOptions(ServiceVersion version = LatestVersion) this.ConfigureLogging(); } + /// + /// Gets or sets whether to disable verification that the authentication challenge resource matches the Key Vault domain. + /// + public bool DisableChallengeResourceVerification { get; set; } + internal string GetVersionString() { return Version switch diff --git a/sdk/keyvault/Azure.Security.KeyVault.Shared/src/ChallengeBasedAuthenticationPolicy.cs b/sdk/keyvault/Azure.Security.KeyVault.Shared/src/ChallengeBasedAuthenticationPolicy.cs index 3bfdb385e8a8..ec82ee2c1d63 100644 --- a/sdk/keyvault/Azure.Security.KeyVault.Shared/src/ChallengeBasedAuthenticationPolicy.cs +++ b/sdk/keyvault/Azure.Security.KeyVault.Shared/src/ChallengeBasedAuthenticationPolicy.cs @@ -13,6 +13,7 @@ namespace Azure.Security.KeyVault internal class ChallengeBasedAuthenticationPolicy : BearerTokenAuthenticationPolicy { private const string KeyVaultStashedContentKey = "KeyVaultContent"; + private readonly bool _verifyChallengeResource; /// /// Challenges are cached using the Key Vault or Managed HSM endpoint URI authority as the key. @@ -20,8 +21,10 @@ internal class ChallengeBasedAuthenticationPolicy : BearerTokenAuthenticationPol private static readonly ConcurrentDictionary s_challengeCache = new(); private ChallengeParameters _challenge; - public ChallengeBasedAuthenticationPolicy(TokenCredential credential) : base(credential, Array.Empty()) - { } + public ChallengeBasedAuthenticationPolicy(TokenCredential credential, bool disableChallengeResourceVerification) : base(credential, Array.Empty()) + { + _verifyChallengeResource = !disableChallengeResourceVerification; + } /// protected override ValueTask AuthorizeRequestAsync(HttpMessage message) @@ -77,6 +80,7 @@ private async ValueTask AuthorizeRequestInternal(HttpMessage message, bool async protected override ValueTask AuthorizeRequestOnChallengeAsync(HttpMessage message) => AuthorizeRequestOnChallengeAsyncInternal(message, true); + /// protected override bool AuthorizeRequestOnChallenge(HttpMessage message) => AuthorizeRequestOnChallengeAsyncInternal(message, false).EnsureCompleted(); @@ -107,6 +111,20 @@ private async ValueTask AuthorizeRequestOnChallengeAsyncInternal(HttpMessa } else { + // Verify the scope domain with leading "." matches the requested host domain. + if (_verifyChallengeResource) + { + if (!Uri.TryCreate(scope, UriKind.Absolute, out Uri scopeUri)) + { + throw new InvalidOperationException($"The challenge contains invalid scope '{scope}'."); + } + + if (!message.Request.Uri.Host.EndsWith($".{scopeUri.Host}", StringComparison.OrdinalIgnoreCase)) + { + throw new InvalidOperationException($"The challenge resource '{scopeUri.Host}' does not match the requested domain. Set DisableChallengeResourceVerification to true in your client options to disable. See https://aka.ms/azsdk/blog/vault-uri for more information."); + } + } + string authorization = AuthorizationChallengeParser.GetChallengeParameterFromResponse(message.Response, "Bearer", "authorization"); if (authorization is null) { diff --git a/sdk/keyvault/samples/sharelink/ManagedStorageRestClient.cs b/sdk/keyvault/samples/sharelink/ManagedStorageRestClient.cs index 41fb53def8fc..9149a4416c92 100644 --- a/sdk/keyvault/samples/sharelink/ManagedStorageRestClient.cs +++ b/sdk/keyvault/samples/sharelink/ManagedStorageRestClient.cs @@ -23,7 +23,7 @@ internal static ManagedStorageRestClient Create(Uri vaultUri, TokenCredential cr { HttpPipeline pipeline = HttpPipelineBuilder.Build( options ?? throw new ArgumentNullException(nameof(options)), - new ChallengeBasedAuthenticationPolicy(credential ?? throw new ArgumentNullException(nameof(credential)))); + new ChallengeBasedAuthenticationPolicy(credential ?? throw new ArgumentNullException(nameof(credential)), true)); ClientDiagnostics diagnostics = new ClientDiagnostics(options); return new ManagedStorageRestClient(diagnostics, pipeline, vaultUri.AbsoluteUri); diff --git a/sdk/keyvault/samples/sharelink/ShareLink.csproj b/sdk/keyvault/samples/sharelink/ShareLink.csproj index 8604dcd4b560..359bdff7f2e0 100644 --- a/sdk/keyvault/samples/sharelink/ShareLink.csproj +++ b/sdk/keyvault/samples/sharelink/ShareLink.csproj @@ -21,21 +21,20 @@ - - + + -