Skip to content

Commit

Permalink
Merge pull request #4 from johnnypham/akv-upgrade
Browse files Browse the repository at this point in the history
Update tests
  • Loading branch information
cheenamalhotra authored Feb 9, 2021
2 parents 52dc29d + d8278f8 commit e54c463
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 35 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,11 @@ internal static class Constants
@"vault.azure.net", // default
@"vault.azure.cn", // Azure China
@"vault.usgovcloudapi.net", // US Government
@"vault.microsoftazure.de" // Azure Germany
@"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
};

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,16 +101,16 @@ public SqlColumnEncryptionAzureKeyVaultProvider(TokenCredential tokenCredential,
/// and an array of trusted endpoints.
/// </summary>
/// <param name="tokenCredential">Instance of an implementation of Token Credential that is capable of providing an OAuth Token</param>
/// <param name="trustedEndPoints">TrustedEndpoints are used to validate the master key path</param>
public SqlColumnEncryptionAzureKeyVaultProvider(TokenCredential tokenCredential, string[] trustedEndPoints)
/// <param name="trustedEndpoints">TrustedEndpoints are used to validate the master key path</param>
public SqlColumnEncryptionAzureKeyVaultProvider(TokenCredential tokenCredential, string[] trustedEndpoints)
{
ValidateNotNull(tokenCredential, nameof(tokenCredential));
ValidateNotNull(trustedEndPoints, nameof(trustedEndPoints));
ValidateNotEmpty(trustedEndPoints, nameof(trustedEndPoints));
ValidateNotNullOrWhitespaceForEach(trustedEndPoints, nameof(trustedEndPoints));
ValidateNotNull(trustedEndpoints, nameof(trustedEndpoints));
ValidateNotEmpty(trustedEndpoints, nameof(trustedEndpoints));
ValidateNotNullOrWhitespaceForEach(trustedEndpoints, nameof(trustedEndpoints));

KeyCryptographer = new AzureSqlKeyCryptographer(tokenCredential);
TrustedEndPoints = trustedEndPoints;
TrustedEndPoints = trustedEndpoints;
}
#endregion

Expand Down Expand Up @@ -242,7 +242,6 @@ public override byte[] EncryptColumnEncryptionKey(string masterKeyPath, string e
{
// Validate the input parameters
ValidateNonEmptyAKVPath(masterKeyPath, isSystemOp: true);
ValidateNotNullOrWhitespace(encryptionAlgorithm, nameof(encryptionAlgorithm));
ValidateEncryptionAlgorithm(encryptionAlgorithm, isSystemOp: true);
ValidateNotNull(columnEncryptionKey, nameof(columnEncryptionKey));
ValidateNotEmpty(columnEncryptionKey, nameof(columnEncryptionKey));
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,8 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="InvalidTrustedEndpointTemplate" xml:space="preserve">
<value>Invalid trusted endpoint specified: '{0}'; a trusted endpoint must have a value.</value>
<data name="NullOrWhitespaceForEach" xml:space="preserve">
<value>One or more of the elements in {0} are null or empty or consist of only whitespace.</value>
</data>
<data name="CipherTextLengthMismatch" xml:space="preserve">
<value>CipherText length does not match the RSA key size.</value>
Expand Down Expand Up @@ -174,4 +174,4 @@
<data name="NullAlgorithmInternal" xml:space="preserve">
<value>Internal error. Key encryption algorithm cannot be null.</value>
</data>
</root>
</root>
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,23 @@ internal static void ValidateNotNullOrWhitespace(string parameter, string name)
{
if (string.IsNullOrWhiteSpace(parameter))
{
throw new ArgumentException(name, Strings.NullOrWhitespaceArgument);
throw new ArgumentException(string.Format(Strings.NullOrWhitespaceArgument, name));
}
}

internal static void ValidateNotEmpty(IList parameter, string name)
{
if (parameter.Count == 0)
{
throw new ArgumentException(name, Strings.EmptyArgumentInternal);
throw new ArgumentException(string.Format(Strings.EmptyArgumentInternal, name));
}
}

internal static void ValidateNotNullOrWhitespaceForEach(string[] parameters, string name)
{
foreach (var parameter in parameters)
if (parameters.Any(s => string.IsNullOrWhiteSpace(s)))
{
if (null == parameter)
{
throw new ArgumentException(parameter, Strings.InvalidTrustedEndpointTemplate);
}
throw new ArgumentException(string.Format(Strings.NullOrWhitespaceForEach, name));
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

using System;
using System.Security.Cryptography;
using Microsoft.Data.SqlClient.AlwaysEncrypted.AzureKeyVaultProvider;
using Microsoft.Data.SqlClient.ManualTesting.Tests.AlwaysEncrypted.Setup;
using Xunit;

Expand Down Expand Up @@ -45,36 +46,36 @@ public void NullEncryptionAlgorithm()
Exception ex1 = Assert.Throws<ArgumentNullException>(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, null, cek));
Assert.Matches($@"Internal error. Key encryption algorithm cannot be null.\s+\(?Parameter (name: )?'?encryptionAlgorithm('\))?", ex1.Message);
Exception ex2 = Assert.Throws<ArgumentNullException>(() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, null, cek));
Assert.Matches($@"Key encryption algorithm cannot be null.\s+\(?Parameter (name: )?'?encryptionAlgorithm('\))?", ex2.Message);
Assert.Matches($@"Internal error. Key encryption algorithm cannot be null.\s+\(?Parameter (name: )?'?encryptionAlgorithm('\))?", ex2.Message);
}


[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))]
public void EmptyColumnEncryptionKey()
{
Exception ex1 = Assert.Throws<ArgumentException>(() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, new byte[] { }));
Assert.Matches($@"Empty column encryption key specified.\s+\(?Parameter (name: )?'?columnEncryptionKey('\))?", ex1.Message);
Assert.Matches($@"Internal error. Empty columnEncryptionKey specified.", ex1.Message);
}

[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))]
public void NullColumnEncryptionKey()
{
Exception ex1 = Assert.Throws<ArgumentNullException>(() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, null));
Assert.Matches($@"Column encryption key cannot be null.\s+\(?Parameter (name: )?'?columnEncryptionKey('\))?", ex1.Message);
Assert.Matches($@"Value cannot be null..\s+\(?Parameter (name: )?'?columnEncryptionKey('\))?", ex1.Message);
}

[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))]
public void EmptyEncryptedColumnEncryptionKey()
{
Exception ex1 = Assert.Throws<ArgumentException>(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, new byte[] { }));
Assert.Matches($@"Internal error. Empty encrypted column encryption key specified.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?", ex1.Message);
Assert.Matches($@"Internal error. Empty encryptedColumnEncryptionKey specified", ex1.Message);
}

[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))]
public void NullEncryptedColumnEncryptionKey()
{
Exception ex1 = Assert.Throws<ArgumentNullException>(() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(DataTestUtility.AKVUrl, MasterKeyEncAlgo, null));
Assert.Matches($@"Internal error. Encrypted column encryption key cannot be null.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?", ex1.Message);
Assert.Matches($@"Value cannot be null.\s+\(?Parameter (name: )?'?encryptedColumnEncryptionKey('\))?", ex1.Message);
}

[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))]
Expand Down Expand Up @@ -152,18 +153,31 @@ public void NullAKVKeyPath()
[ConditionalFact(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))]
public void InvalidCertificatePath()
{
string dummyPath = @"https://www.microsoft.com";
string errorMessage = $@"Invalid Azure Key Vault key path specified: '{dummyPath}'. Valid trusted endpoints: vault.azure.net, vault.azure.cn, vault.usgovcloudapi.net, vault.microsoftazure.de.\s+\(?Parameter (name: )?'?masterKeyPath('\))?";
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);

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

Exception ex1 = Assert.Throws<ArgumentException>(() => fixture.AkvStoreProvider.EncryptColumnEncryptionKey(dummyPath, MasterKeyEncAlgo, cek));
Assert.Matches(errorMessage, ex1.Message);

Exception ex2 = Assert.Throws<ArgumentException>(
() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(dummyPath, MasterKeyEncAlgo, encryptedCek));
Assert.Matches(errorMessage, ex2.Message);
ex = Assert.Throws<ArgumentException>(
() => fixture.AkvStoreProvider.DecryptColumnEncryptionKey(dummyPathWithInvalidKey, MasterKeyEncAlgo, encryptedCek));
Assert.Matches(invalidTrustedEndpointErrorMessage, ex.Message);
}

[InlineData(true)]
[InlineData(true)]
[InlineData(false)]
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))]
public void AkvStoreProviderVerifyFunctionWithInvalidSignature(bool fEnclaveEnabled)
Expand Down Expand Up @@ -206,5 +220,19 @@ public void AkvStoreProviderVerifyFunctionWithInvalidSignature(bool fEnclaveEnab
tamperedCmkSignature[startingByteIndex + randomIndexInCipherText[0]] = cmkSignature[startingByteIndex + randomIndexInCipherText[0]];
}
}

[InlineData(new object[] { new string[] { null } })]
[InlineData(new object[] { new string[] { "" } })]
[InlineData(new object[] { new string[] { " " } })]
[ConditionalTheory(typeof(DataTestUtility), nameof(DataTestUtility.IsAKVSetupAvailable))]
public void InvalidTrustedEndpoints(string[] trustedEndpoints)
{
Exception ex = Assert.Throws<ArgumentException>(() =>
{
SqlColumnEncryptionAzureKeyVaultProvider azureKeyProvider = new SqlColumnEncryptionAzureKeyVaultProvider(
new SqlClientCustomTokenCredential(), trustedEndpoints);
});
Assert.Matches("One or more of the elements in trustedEndpoints are null or empty or consist of only whitespace.", ex.Message);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ static DataTestUtility()
}

AKVOriginalUrl = c.AzureKeyVaultURL;
if (!string.IsNullOrEmpty(AKVOriginalUrl) && Uri.TryCreate(AKVOriginalUrl, UriKind.Absolute, out Uri AKVBaseUri))
if (!string.IsNullOrEmpty(AKVOriginalUrl) && Uri.TryCreate(AKVOriginalUrl, UriKind.Absolute, out AKVBaseUri))
{
AKVBaseUri = new Uri(AKVBaseUri, "/");
AKVBaseUrl = AKVBaseUri.AbsoluteUri;
Expand Down

0 comments on commit e54c463

Please sign in to comment.