Skip to content

Commit 1ccdf40

Browse files
authored
[6.1] Add new trusted AKV URLs for FR and DE (#3486)
* Add new trusted AKV URLs for FR and DE (#3482) - Added 4 new trusted AKV URLs. - Fixed existing manual tests and added unit tests. * - Removed unnecessary strings and console output from TrustedUrlsTest. * - Removed sensitive vault domains.
1 parent 3b59b94 commit 1ccdf40

File tree

5 files changed

+128
-19
lines changed

5 files changed

+128
-19
lines changed

src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Constants.cs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,24 @@ internal static class Constants
99
/// <summary>
1010
/// Azure Key Vault Domain Name
1111
/// </summary>
12-
internal static readonly string[] AzureKeyVaultPublicDomainNames = new string[] {
13-
@"vault.azure.net", // default
14-
@"vault.azure.cn", // Azure China
15-
@"vault.usgovcloudapi.net", // US Government
16-
@"vault.microsoftazure.de", // Azure Germany
17-
@"managedhsm.azure.net", // public HSM vault
18-
@"managedhsm.azure.cn", // Azure China HSM vault
19-
@"managedhsm.usgovcloudapi.net", // US Government HSM vault
20-
@"managedhsm.microsoftazure.de" // Azure Germany HSM vault
21-
};
12+
internal static readonly string[] AzureKeyVaultPublicDomainNames =
13+
[
14+
// Azure Key Vaults
15+
"vault.azure.net", // Default
16+
"vault.azure.cn", // China
17+
"vault.usgovcloudapi.net", // US Government
18+
"vault.microsoftazure.de", // Azure Germany
19+
"vault.sovcloud-api.fr", // France (Bleu)
20+
"vault.sovcloud-api.de", // Germany (Delos)
21+
22+
// Managed High Security Modules (HSM) Vaults
23+
"managedhsm.azure.net",
24+
"managedhsm.azure.cn",
25+
"managedhsm.usgovcloudapi.net",
26+
"managedhsm.microsoftazure.de",
27+
"managedhsm.sovcloud-api.fr",
28+
"managedhsm.sovcloud-api.de"
29+
];
2230

2331
/// <summary>
2432
/// Always Encrypted Parameter names for exec handling

src/Microsoft.Data.SqlClient/add-ons/AzureKeyVaultProvider/Utils.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ internal static ArgumentException InvalidAKVPath(string masterKeyPath, bool isSy
141141
internal static ArgumentException InvalidAKVUrl(string masterKeyPath) =>
142142
new(string.Format(CultureInfo.InvariantCulture, Strings.InvalidAkvUrlTemplate, masterKeyPath), Constants.AeParamMasterKeyPath);
143143

144-
internal static Exception InvalidAKVUrlTrustedEndpoints(string masterKeyPath, string endpoints) =>
144+
internal static ArgumentException InvalidAKVUrlTrustedEndpoints(string masterKeyPath, string endpoints) =>
145145
new ArgumentException(string.Format(CultureInfo.InvariantCulture, Strings.InvalidAkvKeyPathTrustedTemplate, masterKeyPath, endpoints),
146146
Constants.AeParamMasterKeyPath);
147147
}

src/Microsoft.Data.SqlClient/tests/ManualTests/AlwaysEncrypted/ExceptionTestAKVStore.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -182,23 +182,22 @@ public void InvalidCertificatePath()
182182
string dummyPathWithOnlyHost = @"https://www.microsoft.com";
183183
string invalidUrlErrorMessage = $@"Invalid url specified: '{dummyPathWithOnlyHost}'";
184184
string dummyPathWithInvalidKey = @"https://www.microsoft.vault.azure.com/keys/dummykey/dummykeyid";
185-
string invalidTrustedEndpointErrorMessage = $@"Invalid Azure Key Vault key path specified: '{dummyPathWithInvalidKey}'. Valid trusted endpoints: vault.azure.net, vault.azure.cn, vault.usgovcloudapi.net, vault.microsoftazure.de, managedhsm.azure.net, managedhsm.azure.cn, managedhsm.usgovcloudapi.net, managedhsm.microsoftazure.de.\s+\(?Parameter (name: )?'?masterKeyPath('\))?";
186185

187186
Exception ex = Assert.Throws<ArgumentException>(
188187
() => _fixture.AkvStoreProvider.EncryptColumnEncryptionKey(dummyPathWithOnlyHost, MasterKeyEncAlgo, cek));
189188
Assert.Matches(invalidUrlErrorMessage, ex.Message);
190189

191190
ex = Assert.Throws<ArgumentException>(
192191
() => _fixture.AkvStoreProvider.EncryptColumnEncryptionKey(dummyPathWithInvalidKey, MasterKeyEncAlgo, cek));
193-
Assert.Matches(invalidTrustedEndpointErrorMessage, ex.Message);
192+
Assert.Matches(TrustedUrlsTest.MakeInvalidVaultErrorMessage(dummyPathWithInvalidKey), ex.Message);
194193

195194
ex = Assert.Throws<ArgumentException>(
196195
() => _fixture.AkvStoreProvider.DecryptColumnEncryptionKey(dummyPathWithOnlyHost, MasterKeyEncAlgo, encryptedCek));
197196
Assert.Matches(invalidUrlErrorMessage, ex.Message);
198197

199198
ex = Assert.Throws<ArgumentException>(
200199
() => _fixture.AkvStoreProvider.DecryptColumnEncryptionKey(dummyPathWithInvalidKey, MasterKeyEncAlgo, encryptedCek));
201-
Assert.Matches(invalidTrustedEndpointErrorMessage, ex.Message);
200+
Assert.Matches(TrustedUrlsTest.MakeInvalidVaultErrorMessage(dummyPathWithInvalidKey), ex.Message);
202201
}
203202

204203
[InlineData(true)]
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System;
6+
using System.Reflection;
7+
using Azure.Core;
8+
using Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider;
9+
using Xunit;
10+
11+
namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted;
12+
13+
public class TrustedUrlsTest
14+
{
15+
private readonly SqlColumnEncryptionAzureKeyVaultProvider _provider;
16+
private readonly MethodInfo _method;
17+
18+
public TrustedUrlsTest()
19+
{
20+
_provider = new(new SqlClientCustomTokenCredential());
21+
22+
var assembly = typeof(SqlColumnEncryptionAzureKeyVaultProvider).Assembly;
23+
var clazz = assembly.GetType("Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.SqlColumnEncryptionAzureKeyVaultProvider");
24+
_method = clazz.GetMethod(
25+
"ValidateNonEmptyAKVPath",
26+
System.Reflection.BindingFlags.NonPublic |
27+
System.Reflection.BindingFlags.Instance);
28+
}
29+
30+
private static string MakeUrl(string vault)
31+
{
32+
return $"https://{vault}/keys/dummykey/dummykeyid";
33+
}
34+
35+
public static string MakeInvalidVaultErrorMessage(string url)
36+
{
37+
return
38+
$"Invalid Azure Key Vault key path specified: '{url}'. " +
39+
"Valid trusted endpoints: " +
40+
"vault.azure.net, " +
41+
"vault.azure.cn, " +
42+
"vault.usgovcloudapi.net, " +
43+
"vault.microsoftazure.de, " +
44+
"vault.sovcloud-api.fr, " +
45+
"vault.sovcloud-api.de, " +
46+
"managedhsm.azure.net, " +
47+
"managedhsm.azure.cn, " +
48+
"managedhsm.usgovcloudapi.net, " +
49+
"managedhsm.microsoftazure.de, " +
50+
"managedhsm.sovcloud-api.fr, " +
51+
"managedhsm.sovcloud-api.de." +
52+
@"\s+\(?Parameter (name: )?'?masterKeyPath('\))?";
53+
}
54+
55+
[Theory]
56+
[InlineData("www.microsoft.com")]
57+
[InlineData("www.microsoft.vault.azure.com")]
58+
[InlineData("vault.azure.net.io")]
59+
public void InvalidVaults(string vault)
60+
{
61+
// Test that invalid key paths throw and contain the expected error
62+
// message.
63+
var url = MakeUrl(vault);
64+
65+
try
66+
{
67+
_method.Invoke(_provider, new object[] { url, false });
68+
}
69+
catch (TargetInvocationException ex)
70+
{
71+
// Unwrap the exception to get the actual ArgumentException thrown
72+
var argEx = ex.InnerException as ArgumentException;
73+
Assert.NotNull(argEx);
74+
Assert.Matches(MakeInvalidVaultErrorMessage(url), argEx.Message);
75+
}
76+
}
77+
78+
[Theory]
79+
// Normal vaults.
80+
[InlineData("vault.azure.net")]
81+
[InlineData("vault.azure.cn")]
82+
[InlineData("vault.usgovcloudapi.net")]
83+
[InlineData("vault.microsoftazure.de")]
84+
[InlineData("vault.sovcloud-api.fr")]
85+
[InlineData("vault.sovcloud-api.de")]
86+
// HSM vaults.
87+
[InlineData("managedhsm.azure.net")]
88+
[InlineData("managedhsm.azure.cn")]
89+
[InlineData("managedhsm.usgovcloudapi.net")]
90+
[InlineData("managedhsm.microsoftazure.de")]
91+
[InlineData("managedhsm.sovcloud-api.fr")]
92+
[InlineData("managedhsm.sovcloud-api.de")]
93+
// Vaults with prefixes.
94+
[InlineData("foo.bar.vault.microsoftazure.de")]
95+
[InlineData("baz.bar.foo.managedhsm.sovcloud-api.fr")]
96+
public void ValidVaults(string vault)
97+
{
98+
// Test that valid vault key paths do not throw exceptions
99+
_method.Invoke(_provider, new object[] { MakeUrl(vault), false });
100+
}
101+
}

src/Microsoft.Data.SqlClient/tests/ManualTests/Microsoft.Data.SqlClient.ManualTesting.Tests.csproj

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,22 +36,23 @@
3636
<ItemGroup Condition="'$(TestSet)' == '' OR '$(TestSet)' == 'AE'">
3737
<Compile Include="AlwaysEncrypted\AKVTests.cs" />
3838
<Compile Include="AlwaysEncrypted\AKVUnitTests.cs" />
39-
<Compile Include="AlwaysEncrypted\EnclaveAzureDatabaseTests.cs" />
40-
<Compile Include="AlwaysEncrypted\ExceptionTestAKVStore.cs" />
41-
<Compile Include="AlwaysEncrypted\TestFixtures\Setup\AKVTestTable.cs" />
42-
<Compile Include="AlwaysEncrypted\TestFixtures\Setup\AkvColumnMasterKey.cs" />
43-
<Compile Include="AlwaysEncrypted\TestFixtures\SQLSetupStrategyAzureKeyVault.cs" />
4439
<Compile Include="AlwaysEncrypted\ApiShould.cs" />
4540
<Compile Include="AlwaysEncrypted\BulkCopyAE.cs" />
4641
<Compile Include="AlwaysEncrypted\BulkCopyAEErrorMessage.cs" />
4742
<Compile Include="AlwaysEncrypted\ColumnDecryptErrorTests.cs" />
43+
<Compile Include="AlwaysEncrypted\EnclaveAzureDatabaseTests.cs" />
4844
<Compile Include="AlwaysEncrypted\End2EndSmokeTests.cs" />
45+
<Compile Include="AlwaysEncrypted\ExceptionTestAKVStore.cs" />
4946
<Compile Include="AlwaysEncrypted\SqlBulkCopyTruncation.cs" />
5047
<Compile Include="AlwaysEncrypted\SqlNullValues.cs" />
48+
<Compile Include="AlwaysEncrypted\TrustedUrlsTest.cs" />
5149
<Compile Include="AlwaysEncrypted\TestFixtures\AzureKeyVaultKeyFixture.cs" />
5250
<Compile Include="AlwaysEncrypted\TestFixtures\DatabaseHelper.cs" />
5351
<Compile Include="AlwaysEncrypted\TestFixtures\SQLSetupStrategy.cs" />
52+
<Compile Include="AlwaysEncrypted\TestFixtures\SQLSetupStrategyAzureKeyVault.cs" />
5453
<Compile Include="AlwaysEncrypted\TestFixtures\SQLSetupStrategyCertStoreProvider.cs" />
54+
<Compile Include="AlwaysEncrypted\TestFixtures\Setup\AKVTestTable.cs" />
55+
<Compile Include="AlwaysEncrypted\TestFixtures\Setup\AkvColumnMasterKey.cs" />
5556
<Compile Include="AlwaysEncrypted\TestFixtures\Setup\ApiTestTable.cs" />
5657
<Compile Include="AlwaysEncrypted\TestFixtures\Setup\BulkCopyAETestTable.cs" />
5758
<Compile Include="AlwaysEncrypted\TestFixtures\Setup\BulkCopyAEErrorMessageTestTable.cs" />

0 commit comments

Comments
 (0)