Skip to content

[6.0] Add new trusted AKV URLs for FR and DE #3485

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: release/6.0
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,24 @@ internal static class Constants
/// <summary>
/// Azure Key Vault Domain Name
/// </summary>
internal static readonly string[] AzureKeyVaultPublicDomainNames = new string[] {
@"vault.azure.net", // default
@"vault.azure.cn", // Azure China
@"vault.usgovcloudapi.net", // US Government
@"vault.microsoftazure.de", // Azure Germany
@"managedhsm.azure.net", // public HSM vault
@"managedhsm.azure.cn", // Azure China HSM vault
@"managedhsm.usgovcloudapi.net", // US Government HSM vault
@"managedhsm.microsoftazure.de" // Azure Germany HSM vault
internal static readonly string[] AzureKeyVaultPublicDomainNames =
new string[]
{
// Azure Key Vaults
"vault.azure.net", // Default
"vault.azure.cn", // China
"vault.usgovcloudapi.net", // US Government
"vault.microsoftazure.de", // Azure Germany
"vault.sovcloud-api.fr", // France (Bleu)
"vault.sovcloud-api.de", // Germany (Delos)

// Managed High Security Modules (HSM) Vaults
"managedhsm.azure.net",
"managedhsm.azure.cn",
"managedhsm.usgovcloudapi.net",
"managedhsm.microsoftazure.de",
"managedhsm.sovcloud-api.fr",
"managedhsm.sovcloud-api.de"
};

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ internal static ArgumentException InvalidAKVPath(string masterKeyPath, bool isSy
internal static ArgumentException InvalidAKVUrl(string masterKeyPath) =>
new(string.Format(CultureInfo.InvariantCulture, Strings.InvalidAkvUrlTemplate, masterKeyPath), Constants.AeParamMasterKeyPath);

internal static Exception InvalidAKVUrlTrustedEndpoints(string masterKeyPath, string endpoints) =>
internal static ArgumentException InvalidAKVUrlTrustedEndpoints(string masterKeyPath, string endpoints) =>
new ArgumentException(string.Format(CultureInfo.InvariantCulture, Strings.InvalidAkvKeyPathTrustedTemplate, masterKeyPath, endpoints),
Constants.AeParamMasterKeyPath);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,23 +182,22 @@ public void InvalidCertificatePath()
string dummyPathWithOnlyHost = @"https://www.microsoft.com";
string invalidUrlErrorMessage = $@"Invalid url specified: '{dummyPathWithOnlyHost}'";
string dummyPathWithInvalidKey = @"https://www.microsoft.vault.azure.com/keys/dummykey/dummykeyid";
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('\))?";

Exception ex = Assert.Throws<ArgumentException>(
() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(dummyPathWithOnlyHost, MasterKeyEncAlgo, cek));
Assert.Matches(invalidUrlErrorMessage, ex.Message);

ex = Assert.Throws<ArgumentException>(
() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(dummyPathWithInvalidKey, MasterKeyEncAlgo, cek));
Assert.Matches(invalidTrustedEndpointErrorMessage, ex.Message);
Assert.Matches(TrustedUrlsTest.MakeInvalidVaultErrorMessage(dummyPathWithInvalidKey), ex.Message);

ex = Assert.Throws<ArgumentException>(
() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(dummyPathWithOnlyHost, MasterKeyEncAlgo, encryptedCek));
Assert.Matches(invalidUrlErrorMessage, ex.Message);

ex = Assert.Throws<ArgumentException>(
() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(dummyPathWithInvalidKey, MasterKeyEncAlgo, encryptedCek));
Assert.Matches(invalidTrustedEndpointErrorMessage, ex.Message);
Assert.Matches(TrustedUrlsTest.MakeInvalidVaultErrorMessage(dummyPathWithInvalidKey), ex.Message);
}

[InlineData(true)]
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Reflection;
using Azure.Core;
using Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider;
using Xunit;

namespace Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted
{
public class TrustedUrlsTest
{
private readonly SqlColumnEncryptionAzureKeyVaultProvider _provider;
private readonly MethodInfo _method;

public TrustedUrlsTest()
{
_provider = new(new SqlClientCustomTokenCredential());

var assembly = typeof(SqlColumnEncryptionAzureKeyVaultProvider).Assembly;
var clazz = assembly.GetType("Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider.SqlColumnEncryptionAzureKeyVaultProvider");
_method = clazz.GetMethod(
"ValidateNonEmptyAKVPath",
System.Reflection.BindingFlags.NonPublic |
System.Reflection.BindingFlags.Instance);
}

private static string MakeUrl(string vault)
{
return $"https://{vault}/keys/dummykey/dummykeyid";
}

public static string MakeInvalidVaultErrorMessage(string url)
{
return
$"Invalid Azure Key Vault key path specified: '{url}'. " +
"Valid trusted endpoints: " +
"vault.azure.net, " +
"vault.azure.cn, " +
"vault.usgovcloudapi.net, " +
"vault.microsoftazure.de, " +
"vault.sovcloud-api.fr, " +
"vault.sovcloud-api.de, " +
"managedhsm.azure.net, " +
"managedhsm.azure.cn, " +
"managedhsm.usgovcloudapi.net, " +
"managedhsm.microsoftazure.de, " +
"managedhsm.sovcloud-api.fr, " +
"managedhsm.sovcloud-api.de." +
@"\s+\(?Parameter (name: )?'?masterKeyPath('\))?";
}

[Theory]
[InlineData("www.microsoft.com")]
[InlineData("www.microsoft.vault.azure.com")]
[InlineData("vault.azure.net.io")]
public void InvalidVaults(string vault)
{
// Test that invalid key paths throw and contain the expected error
// message.
var url = MakeUrl(vault);

try
{
_method.Invoke(_provider, new object[] { url, false });
}
catch (TargetInvocationException ex)
{
// Unwrap the exception to get the actual ArgumentException thrown
var argEx = ex.InnerException as ArgumentException;
Assert.NotNull(argEx);
Assert.Matches(MakeInvalidVaultErrorMessage(url), argEx.Message);
}
}

[Theory]
// Normal vaults.
[InlineData("vault.azure.net")]
[InlineData("vault.azure.cn")]
[InlineData("vault.usgovcloudapi.net")]
[InlineData("vault.microsoftazure.de")]
[InlineData("vault.sovcloud-api.fr")]
[InlineData("vault.sovcloud-api.de")]
// HSM vaults.
[InlineData("managedhsm.azure.net")]
[InlineData("managedhsm.azure.cn")]
[InlineData("managedhsm.usgovcloudapi.net")]
[InlineData("managedhsm.microsoftazure.de")]
[InlineData("managedhsm.sovcloud-api.fr")]
[InlineData("managedhsm.sovcloud-api.de")]
// Vaults with prefixes.
[InlineData("foo.bar.vault.microsoftazure.de")]
[InlineData("baz.bar.foo.managedhsm.sovcloud-api.fr")]
public void ValidVaults(string vault)
{
// Test that valid vault key paths do not throw exceptions
_method.Invoke(_provider, new object[] { MakeUrl(vault), false });
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,21 +37,22 @@
<ItemGroup Condition="'$(TestSet)' == '' OR '$(TestSet)' == 'AE'">
<Compile Include="AlwaysEncrypted\AKVTests.cs" />
<Compile Include="AlwaysEncrypted\AKVUnitTests.cs" />
<Compile Include="AlwaysEncrypted\EnclaveAzureDatabaseTests.cs" />
<Compile Include="AlwaysEncrypted\ExceptionTestAKVStore.cs" />
<Compile Include="AlwaysEncrypted\TestFixtures\Setup\AKVTestTable.cs" />
<Compile Include="AlwaysEncrypted\TestFixtures\Setup\AkvColumnMasterKey.cs" />
<Compile Include="AlwaysEncrypted\TestFixtures\SQLSetupStrategyAzureKeyVault.cs" />
<Compile Include="AlwaysEncrypted\ApiShould.cs" />
<Compile Include="AlwaysEncrypted\BulkCopyAE.cs" />
<Compile Include="AlwaysEncrypted\BulkCopyAEErrorMessage.cs" />
<Compile Include="AlwaysEncrypted\ColumnDecryptErrorTests.cs" />
<Compile Include="AlwaysEncrypted\EnclaveAzureDatabaseTests.cs" />
<Compile Include="AlwaysEncrypted\End2EndSmokeTests.cs" />
<Compile Include="AlwaysEncrypted\ExceptionTestAKVStore.cs" />
<Compile Include="AlwaysEncrypted\SqlBulkCopyTruncation.cs" />
<Compile Include="AlwaysEncrypted\SqlNullValues.cs" />
<Compile Include="AlwaysEncrypted\TrustedUrlsTest.cs" />
<Compile Include="AlwaysEncrypted\TestFixtures\DatabaseHelper.cs" />
<Compile Include="AlwaysEncrypted\TestFixtures\SQLSetupStrategy.cs" />
<Compile Include="AlwaysEncrypted\TestFixtures\SQLSetupStrategyAzureKeyVault.cs" />
<Compile Include="AlwaysEncrypted\TestFixtures\SQLSetupStrategyCertStoreProvider.cs" />
<Compile Include="AlwaysEncrypted\TestFixtures\Setup\AKVTestTable.cs" />
<Compile Include="AlwaysEncrypted\TestFixtures\Setup\AkvColumnMasterKey.cs" />
<Compile Include="AlwaysEncrypted\TestFixtures\Setup\ApiTestTable.cs" />
<Compile Include="AlwaysEncrypted\TestFixtures\Setup\BulkCopyAETestTable.cs" />
<Compile Include="AlwaysEncrypted\TestFixtures\Setup\BulkCopyAEErrorMessageTestTable.cs" />
Expand Down
Loading