Skip to content

Commit bb4c3b7

Browse files
authored
Tests | Remove hardcoded certificates from functional tests (#3034)
* Remove default .pfx file from TDS.Servers Clients requiring a server certificate will need to generate their own. * Infrastructure work - base class, project targets * TestUtilities no longer targets netstandard2.0, so is now able to use CertificateRequest. * Added a reference from Tests to TestUtilities. * Added a base CertificateFixtureBase class. This provides basic infrastructure to generate a certificate and add it to a store (with cleanup on disposal.) * Reworked SqlColumnEncryptionCertificateStoreProviderShould Removed multiple hardcoded references to three certificates. Also removed references to TestCertificate12. * Cleanup: ExceptionsCertStore This test class covered similar ground to the existing SqlColumnEncryptionCertificateStoreProviderShould test class. * Rework ExceptionsAlgorithmErrors Removes the last reference to Utility.CreateCertificate, replacing it with one which is generated dynamically. Accordingly, removes Utility.CreateCertificate. * Collection fixtures are unnecessary * Update build.proj * Running PowerShell with "runas" verb * Switched to new .NET 9.0 APIs
1 parent 85044cd commit bb4c3b7

File tree

14 files changed

+432
-411
lines changed

14 files changed

+432
-411
lines changed

build.proj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@
5959
<FunctionalTests Include="**/tools/TDS/TDS/TDS.csproj" />
6060
<FunctionalTests Include="**/tools/TDS/TDS.EndPoint/TDS.EndPoint.csproj" />
6161
<FunctionalTests Include="**/tools/TDS/TDS.Servers/TDS.Servers.csproj" />
62+
<FunctionalTests Include="**/tools/Microsoft.Data.SqlClient.TestUtilities/Microsoft.Data.SqlClient.TestUtilities.csproj"/>
6263
<FunctionalTests Include="**/tools/CoreFx.Private.TestUtilities/CoreFx.Private.TestUtilities.csproj" />
6364
<FunctionalTests Include="**/ManualTests/SQL/UdtTest/UDTs/Address/Address.csproj" />
6465
<FunctionalTests Include="**/FunctionalTests/Microsoft.Data.SqlClient.Tests.csproj" />

src/Microsoft.Data.SqlClient/tests/FunctionalTests/AlwaysEncryptedTests/ExceptionsAlgorithmErrors.cs

Lines changed: 41 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,38 @@
77
using System.Reflection;
88
using System.Security.Cryptography.X509Certificates;
99
using System.Text;
10+
using Microsoft.Data.SqlClient.TestUtilities.Fixtures;
1011
using Xunit;
1112
using static Microsoft.Data.SqlClient.Tests.AlwaysEncryptedTests.Utility;
1213

1314
namespace Microsoft.Data.SqlClient.Tests.AlwaysEncryptedTests
1415
{
15-
public class ExceptionsAlgorithmErrors : IClassFixture<CertFixture>
16+
public class ExceptionsAlgorithmErrors : IClassFixture<ColumnEncryptionCertificateFixture>
1617
{
1718
// Reflection
1819
public static Assembly systemData = Assembly.GetAssembly(typeof(SqlConnection));
1920
public static Type sqlClientSymmetricKey = systemData.GetType("Microsoft.Data.SqlClient.SqlClientSymmetricKey");
2021
public static ConstructorInfo sqlColumnEncryptionKeyConstructor = sqlClientSymmetricKey.GetConstructor(BindingFlags.NonPublic | BindingFlags.Instance, null, new Type[] { typeof(byte[]) }, null);
2122

23+
private readonly ColumnEncryptionCertificateFixture _fixture;
24+
private readonly byte[] _cek;
25+
private readonly byte[] _encryptedCek;
26+
private readonly string _certificatePath;
27+
28+
public ExceptionsAlgorithmErrors(ColumnEncryptionCertificateFixture fixture)
29+
{
30+
// Disable the cache to avoid false failures.
31+
SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled = false;
32+
33+
SqlColumnEncryptionCertificateStoreProvider provider = new SqlColumnEncryptionCertificateStoreProvider();
34+
X509Certificate2 currUserCertificate = fixture.GetCertificate(StoreLocation.CurrentUser);
35+
36+
_cek = GenerateRandomBytes(32);
37+
_fixture = fixture;
38+
_certificatePath = string.Format("CurrentUser/My/{0}", currUserCertificate.Thumbprint);
39+
_encryptedCek = provider.EncryptColumnEncryptionKey(_certificatePath, "RSA_OAEP", _cek);
40+
}
41+
2242
[Fact]
2343
[PlatformSpecific(TestPlatforms.Windows)]
2444
public void TestNullCEK()
@@ -52,9 +72,9 @@ public void TestInvalidEncryptionType()
5272
{
5373
const byte invalidEncryptionType = 3;
5474
Object cipherMD = GetSqlCipherMetadata(0, 2, null, invalidEncryptionType, 0x01);
55-
AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP");
75+
AddEncryptionKeyToCipherMD(cipherMD, _encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, _certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP");
5676
byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld");
57-
byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic);
77+
byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic);
5878

5979
string expectedMessage = string.Format(SystemDataResourceManager.Instance.TCE_InvalidEncryptionType,
6080
"AEAD_AES_256_CBC_HMAC_SHA256", invalidEncryptionType, "'Deterministic', 'Randomized'");
@@ -74,7 +94,7 @@ public void TestInvalidCipherText()
7494
string expectedMessage = string.Format(SystemDataResourceManager.Instance.TCE_InvalidCipherTextSize,
7595
invalidCiphertextLength, 65);
7696
byte[] cipherText = GenerateRandomBytes(invalidCiphertextLength); // minimum length is 65
77-
TargetInvocationException e = Assert.Throws<TargetInvocationException>(() => DecryptDataUsingAED(cipherText, CertFixture.cek, CColumnEncryptionType.Deterministic));
97+
TargetInvocationException e = Assert.Throws<TargetInvocationException>(() => DecryptDataUsingAED(cipherText, _cek, CColumnEncryptionType.Deterministic));
7898
Assert.Contains(expectedMessage, e.InnerException.Message);
7999
}
80100

@@ -85,10 +105,10 @@ public void TestInvalidAlgorithmVersion()
85105
string expectedMessage = string.Format(SystemDataResourceManager.Instance.TCE_InvalidAlgorithmVersion,
86106
40, "01");
87107
byte[] plainText = Encoding.Unicode.GetBytes("Hello World");
88-
byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic);
108+
byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic);
89109
// Put a version number of 0x10
90110
cipherText[0] = 0x40;
91-
TargetInvocationException e = Assert.Throws<TargetInvocationException>(() => DecryptDataUsingAED(cipherText, CertFixture.cek, CColumnEncryptionType.Deterministic));
111+
TargetInvocationException e = Assert.Throws<TargetInvocationException>(() => DecryptDataUsingAED(cipherText, _cek, CColumnEncryptionType.Deterministic));
92112
Assert.Contains(expectedMessage, e.InnerException.Message);
93113
}
94114

@@ -98,13 +118,13 @@ public void TestInvalidAuthenticationTag()
98118
{
99119
string expectedMessage = SystemDataResourceManager.Instance.TCE_InvalidAuthenticationTag;
100120
byte[] plainText = Encoding.Unicode.GetBytes("Hello World");
101-
byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic);
121+
byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic);
102122
// Zero out 4 bytes of authentication tag
103123
for (int i = 0; i < 4; i++)
104124
{
105125
cipherText[i + 1] = 0x00;
106126
}
107-
TargetInvocationException e = Assert.Throws<TargetInvocationException>(() => DecryptDataUsingAED(cipherText, CertFixture.cek, CColumnEncryptionType.Deterministic));
127+
TargetInvocationException e = Assert.Throws<TargetInvocationException>(() => DecryptDataUsingAED(cipherText, _cek, CColumnEncryptionType.Deterministic));
108128
Assert.Contains(expectedMessage, e.InnerException.Message);
109129
}
110130

@@ -115,9 +135,9 @@ public void TestNullColumnEncryptionAlgorithm()
115135
string expectedMessage = string.Format(SystemDataResourceManager.Instance.TCE_NullColumnEncryptionAlgorithm,
116136
"'AEAD_AES_256_CBC_HMAC_SHA256'");
117137
Object cipherMD = GetSqlCipherMetadata(0, 0, null, 1, 0x01);
118-
AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP");
138+
AddEncryptionKeyToCipherMD(cipherMD, _encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, _certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP");
119139
byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld");
120-
byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic);
140+
byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic);
121141

122142
TargetInvocationException e = Assert.Throws<TargetInvocationException>(() => DecryptWithKey(cipherText, cipherMD));
123143
Assert.Contains(expectedMessage, e.InnerException.Message);
@@ -133,9 +153,9 @@ public void TestUnknownEncryptionAlgorithmId()
133153
string expectedMessage = string.Format(SystemDataResourceManager.Instance.TCE_UnknownColumnEncryptionAlgorithmId,
134154
unknownEncryptionAlgoId, "'1', '2'");
135155
Object cipherMD = GetSqlCipherMetadata(0, unknownEncryptionAlgoId, null, 1, 0x01);
136-
AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP");
156+
AddEncryptionKeyToCipherMD(cipherMD, _encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, _certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP");
137157
byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld");
138-
byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic);
158+
byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic);
139159

140160
Exception decryptEx = Assert.Throws<TargetInvocationException>(() => DecryptWithKey(plainText, cipherMD));
141161
Assert.Matches(expectedMessage, decryptEx.InnerException.Message);
@@ -157,9 +177,9 @@ public void TestUnknownCustomKeyStoreProvider()
157177
string expectedMessage = string.Format(SystemDataResourceManager.Instance.TCE_UnrecognizedKeyStoreProviderName,
158178
invalidProviderName, "'MSSQL_CERTIFICATE_STORE', 'MSSQL_CNG_STORE', 'MSSQL_CSP_PROVIDER'", "");
159179
Object cipherMD = GetSqlCipherMetadata(0, 1, null, 1, 0x03);
160-
AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, invalidProviderName, "RSA_OAEP");
180+
AddEncryptionKeyToCipherMD(cipherMD, _encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, _certificatePath, invalidProviderName, "RSA_OAEP");
161181
byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld");
162-
byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic);
182+
byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic);
163183

164184
Exception decryptEx = Assert.Throws<TargetInvocationException>(() => DecryptWithKey(plainText, cipherMD));
165185
Assert.Contains(expectedMessage, decryptEx.InnerException.Message);
@@ -179,9 +199,9 @@ public void TestTceUnknownEncryptionAlgorithm()
179199
string expectedMessage = string.Format(SystemDataResourceManager.Instance.TCE_UnknownColumnEncryptionAlgorithm,
180200
unknownEncryptionAlgorithm, "'AEAD_AES_256_CBC_HMAC_SHA256'");
181201
Object cipherMD = GetSqlCipherMetadata(0, 0, "Dummy", 1, 0x01);
182-
AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP");
202+
AddEncryptionKeyToCipherMD(cipherMD, _encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, _certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP");
183203
byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld");
184-
byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic);
204+
byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic);
185205

186206
Exception decryptEx = Assert.Throws<TargetInvocationException>(() => DecryptWithKey(cipherText, cipherMD));
187207
Assert.Contains(expectedMessage, decryptEx.InnerException.Message);
@@ -194,15 +214,15 @@ public void TestTceUnknownEncryptionAlgorithm()
194214
[PlatformSpecific(TestPlatforms.Windows)]
195215
public void TestExceptionsFromCertStore()
196216
{
197-
byte[] corruptedCek = GenerateInvalidEncryptedCek(CertFixture.cek, ECEKCorruption.SIGNATURE);
217+
byte[] corruptedCek = GenerateInvalidEncryptedCek(_cek, ECEKCorruption.SIGNATURE);
198218

199219
string expectedMessage = string.Format(SystemDataResourceManager.Instance.TCE_KeyDecryptionFailedCertStore,
200220
"MSSQL_CERTIFICATE_STORE", BitConverter.ToString(corruptedCek, corruptedCek.Length - 10, 10));
201221

202222
Object cipherMD = GetSqlCipherMetadata(0, 1, null, 1, 0x01);
203-
AddEncryptionKeyToCipherMD(cipherMD, corruptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP");
223+
AddEncryptionKeyToCipherMD(cipherMD, corruptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, _certificatePath, "MSSQL_CERTIFICATE_STORE", "RSA_OAEP");
204224
byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld");
205-
byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic);
225+
byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic);
206226

207227
Exception decryptEx = Assert.Throws<TargetInvocationException>(() => DecryptWithKey(cipherText, cipherMD));
208228
Assert.Matches(expectedMessage, decryptEx.InnerException.Message);
@@ -224,9 +244,9 @@ public void TestExceptionsFromCustomKeyStore()
224244
SqlConnection.RegisterColumnEncryptionKeyStoreProviders(customProviders);
225245

226246
object cipherMD = GetSqlCipherMetadata(0, 1, null, 1, 0x01);
227-
AddEncryptionKeyToCipherMD(cipherMD, CertFixture.encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, CertFixture.certificatePath, "DummyProvider", "DummyAlgo");
247+
AddEncryptionKeyToCipherMD(cipherMD, _encryptedCek, 0, 0, 0, new byte[] { 0x01, 0x02, 0x03 }, _certificatePath, "DummyProvider", "DummyAlgo");
228248
byte[] plainText = Encoding.Unicode.GetBytes("HelloWorld");
229-
byte[] cipherText = EncryptDataUsingAED(plainText, CertFixture.cek, CColumnEncryptionType.Deterministic);
249+
byte[] cipherText = EncryptDataUsingAED(plainText, _cek, CColumnEncryptionType.Deterministic);
230250

231251
Exception decryptEx = Assert.Throws<TargetInvocationException>(() => DecryptWithKey(cipherText, cipherMD));
232252
Assert.Contains(expectedMessage, decryptEx.InnerException.Message);
@@ -238,35 +258,4 @@ public void TestExceptionsFromCustomKeyStore()
238258
}
239259
}
240260
}
241-
242-
public class CertFixture : IDisposable
243-
{
244-
private readonly SqlColumnEncryptionCertificateStoreProvider provider = new SqlColumnEncryptionCertificateStoreProvider();
245-
246-
public static X509Certificate2 certificate;
247-
public static string thumbprint;
248-
public static string certificatePath;
249-
public static byte[] cek;
250-
public static byte[] encryptedCek;
251-
252-
public CertFixture()
253-
{
254-
if (certificate == null)
255-
{
256-
certificate = Utility.CreateCertificate();
257-
}
258-
thumbprint = certificate.Thumbprint;
259-
certificatePath = string.Format("CurrentUser/My/{0}", thumbprint);
260-
cek = GenerateRandomBytes(32);
261-
encryptedCek = provider.EncryptColumnEncryptionKey(certificatePath, "RSA_OAEP", cek);
262-
263-
// Disable the cache to avoid false failures.
264-
SqlConnection.ColumnEncryptionQueryMetadataCacheEnabled = false;
265-
}
266-
267-
public void Dispose()
268-
{
269-
// Do NOT remove certificate for concurrent consistency. Certificates are used for other test cases as well.
270-
}
271-
}
272261
}

0 commit comments

Comments
 (0)