Skip to content

Commit 318b5e1

Browse files
authored
Cross-platform SqlColumnEncryptionCertificateStoreProvider support (#3014)
* Enabling certificate store provider for Unix platforms * Initial round of cross-platform test enablement * Account for exception message changes between .NET Framework and .NET Core * Initial work to enable Unix support. * Only allow the use of the CurrentUser location for certificates. * Changed the PublishTestResults@2 step to ensure that failed tests are also published. * Moved certificates to external .pfx files, set a password in an effort to fix problems importing these files on MacOS * Moved certificates to external .pfx files, set a password in an effort to fix problems importing these files on MacOS * Added extra Unix-specific exceptions Converting more unusually-embedded PFX files into embedded resources * macOS issue when handling a certificate without a private key. Eliminating possibility of a certificate with a private key having been previously added to the user certificate store. * Correct merge issue - re-remove Unix-specific file * Address test failures on Windows and Linux * Always add a certificate's CN as a SAN * Account for MacOS KeyStorageFlags quirk MacOS will throw an exception when adding a certificate to the user store if the PersistKeySet key storage flag is set. Instead, use the UserKeySet flag.
1 parent f5823c1 commit 318b5e1

22 files changed

+236
-231
lines changed

eng/pipelines/common/templates/steps/publish-test-results-step.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ steps:
3838
TestResults/*.trx
3939
TestResults/**/*.coverage
4040
testRunTitle: 'Linux Tests'
41+
condition: succeededOrFailed()
4142

4243
- powershell: |
4344
cd TestResults

src/Microsoft.Data.SqlClient/netcore/src/Microsoft.Data.SqlClient.csproj

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,9 @@
561561
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlCollation.cs">
562562
<Link>Microsoft\Data\SqlClient\SqlCollation.cs</Link>
563563
</Compile>
564+
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlColumnEncryptionCertificateStoreProvider.cs">
565+
<Link>Microsoft\Data\SqlClient\SqlColumnEncryptionCertificateStoreProvider.cs</Link>
566+
</Compile>
564567
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlColumnEncryptionEnclaveProvider.cs">
565568
<Link>Microsoft\Data\SqlClient\SqlColumnEncryptionEnclaveProvider.cs</Link>
566569
</Compile>
@@ -951,9 +954,6 @@
951954
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SSPI\NativeSspiContextProvider.cs">
952955
<Link>Microsoft\Data\SqlClient\SSPI\NativeSspiContextProvider.cs</Link>
953956
</Compile>
954-
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlColumnEncryptionCertificateStoreProvider.Windows.cs">
955-
<Link>Microsoft\Data\SqlClient\SqlColumnEncryptionCertificateStoreProvider.Windows.cs</Link>
956-
</Compile>
957957
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\TdsParserSafeHandles.Windows.cs">
958958
<Link>Microsoft\Data\SqlClient\TdsParserSafeHandles.Windows.cs</Link>
959959
</Compile>
@@ -995,9 +995,6 @@
995995
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SessionHandle.netcore.Unix.cs">
996996
<Link>Microsoft\Data\SqlClient\SessionHandle.netcore.Unix.cs</Link>
997997
</Compile>
998-
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlColumnEncryptionCertificateStoreProvider.netcore.Unix.cs">
999-
<Link>Microsoft\Data\SqlClinet\SqlColumnEncryptionCertificateStoreProvider.netcore.Unix.cs</Link>
1000-
</Compile>
1001998
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlColumnEncryptionCngProvider.netcore.Unix.cs">
1002999
<Link>Microsoft\Data\SqlClinet\SqlColumnEncryptionCngProvider.netcore.Unix.cs</Link>
10031000
</Compile>

src/Microsoft.Data.SqlClient/netfx/src/Microsoft.Data.SqlClient.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -669,7 +669,7 @@
669669
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlCollation.cs">
670670
<Link>Microsoft\Data\SqlClient\SqlCollation.cs</Link>
671671
</Compile>
672-
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlColumnEncryptionCertificateStoreProvider.Windows.cs">
672+
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlColumnEncryptionCertificateStoreProvider.cs">
673673
<Link>Microsoft\Data\SqlClient\SqlColumnEncryptionCertificateStoreProvider.cs</Link>
674674
</Compile>
675675
<Compile Include="$(CommonSourceRoot)Microsoft\Data\SqlClient\SqlColumnEncryptionCngProvider.Windows.cs">
Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,9 @@ private void ValidateCertificatePathLength(string masterKeyPath, bool isSystemOp
324324
/// </summary>
325325
private string[] GetValidCertificateLocations()
326326
{
327-
return new string[2] { CertLocationLocalMachine, CertLocationCurrentUser };
327+
return Environment.OSVersion.Platform == PlatformID.Win32NT
328+
? new string[2] { CertLocationLocalMachine, CertLocationCurrentUser }
329+
: new string[1] { CertLocationCurrentUser };
328330
}
329331

330332
/// <summary>
@@ -372,7 +374,8 @@ private X509Certificate2 GetCertificateByPath(string keyPath, bool isSystemOp)
372374
// Extract the store location where the cert is stored
373375
if (certParts.Length > 2)
374376
{
375-
if (string.Equals(certParts[0], CertLocationLocalMachine, StringComparison.OrdinalIgnoreCase) == true)
377+
if (string.Equals(certParts[0], CertLocationLocalMachine, StringComparison.OrdinalIgnoreCase) == true
378+
&& Environment.OSVersion.Platform == PlatformID.Win32NT)
376379
{
377380
storeLocation = StoreLocation.LocalMachine;
378381
}

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlColumnEncryptionCertificateStoreProvider.netcore.Unix.cs

Lines changed: 0 additions & 72 deletions
This file was deleted.

src/Microsoft.Data.SqlClient/src/Microsoft/Data/SqlClient/SqlUtil.cs

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1523,14 +1523,29 @@ internal static Exception LargeCertificatePathLength(int actualLength, int maxLe
15231523

15241524
internal static Exception NullCertificatePath(string[] validLocations, bool isSystemOp)
15251525
{
1526-
Debug.Assert(2 == validLocations.Length);
1527-
if (isSystemOp)
1526+
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
15281527
{
1529-
return ADP.ArgumentNull(TdsEnums.TCE_PARAM_MASTERKEY_PATH, StringsHelper.GetString(Strings.TCE_NullCertificatePathSysErr, validLocations[0], validLocations[1], @"/"));
1528+
Debug.Assert(validLocations.Length == 2);
1529+
if (isSystemOp)
1530+
{
1531+
return ADP.ArgumentNull(TdsEnums.TCE_PARAM_MASTERKEY_PATH, StringsHelper.GetString(Strings.TCE_NullCertificatePathSysErr, validLocations[0], validLocations[1], @"/"));
1532+
}
1533+
else
1534+
{
1535+
return ADP.ArgumentNull(TdsEnums.TCE_PARAM_MASTERKEY_PATH, StringsHelper.GetString(Strings.TCE_NullCertificatePath, validLocations[0], validLocations[1], @"/"));
1536+
}
15301537
}
15311538
else
15321539
{
1533-
return ADP.ArgumentNull(TdsEnums.TCE_PARAM_MASTERKEY_PATH, StringsHelper.GetString(Strings.TCE_NullCertificatePath, validLocations[0], validLocations[1], @"/"));
1540+
Debug.Assert(validLocations.Length == 1);
1541+
if (isSystemOp)
1542+
{
1543+
return ADP.ArgumentNull(TdsEnums.TCE_PARAM_MASTERKEY_PATH, StringsHelper.GetString(Strings.TCE_NullCertificatePathSysErr_Unix, validLocations[0], @"/"));
1544+
}
1545+
else
1546+
{
1547+
return ADP.ArgumentNull(TdsEnums.TCE_PARAM_MASTERKEY_PATH, StringsHelper.GetString(Strings.TCE_NullCertificatePath_Unix, validLocations[0], @"/"));
1548+
}
15341549
}
15351550
}
15361551

@@ -1560,14 +1575,29 @@ internal static Exception NullCngKeyPath(bool isSystemOp)
15601575

15611576
internal static Exception InvalidCertificatePath(string actualCertificatePath, string[] validLocations, bool isSystemOp)
15621577
{
1563-
Debug.Assert(2 == validLocations.Length);
1564-
if (isSystemOp)
1578+
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
15651579
{
1566-
return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCertificatePathSysErr, actualCertificatePath, validLocations[0], validLocations[1], @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH);
1580+
Debug.Assert(validLocations.Length == 2);
1581+
if (isSystemOp)
1582+
{
1583+
return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCertificatePathSysErr, actualCertificatePath, validLocations[0], validLocations[1], @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH);
1584+
}
1585+
else
1586+
{
1587+
return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCertificatePath, actualCertificatePath, validLocations[0], validLocations[1], @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH);
1588+
}
15671589
}
15681590
else
15691591
{
1570-
return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCertificatePath, actualCertificatePath, validLocations[0], validLocations[1], @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH);
1592+
Debug.Assert(validLocations.Length == 1);
1593+
if (isSystemOp)
1594+
{
1595+
return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCertificatePathSysErr_Unix, actualCertificatePath, validLocations[0], @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH);
1596+
}
1597+
else
1598+
{
1599+
return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCertificatePath_Unix, actualCertificatePath, validLocations[0], @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH);
1600+
}
15711601
}
15721602
}
15731603

@@ -1681,17 +1711,29 @@ internal static Exception InvalidCngKey(string masterKeyPath, string cngProvider
16811711

16821712
internal static Exception InvalidCertificateLocation(string certificateLocation, string certificatePath, string[] validLocations, bool isSystemOp)
16831713
{
1684-
1685-
#if NETFRAMEWORK
1686-
Debug.Assert(2 == validLocations.Length);
1687-
#endif
1688-
if (isSystemOp)
1714+
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
16891715
{
1690-
return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCertificateLocationSysErr, certificateLocation, certificatePath, validLocations[0], validLocations[1], @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH);
1716+
Debug.Assert(validLocations.Length == 2);
1717+
if (isSystemOp)
1718+
{
1719+
return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCertificateLocationSysErr, certificateLocation, certificatePath, validLocations[0], validLocations[1], @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH);
1720+
}
1721+
else
1722+
{
1723+
return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCertificateLocation, certificateLocation, certificatePath, validLocations[0], validLocations[1], @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH);
1724+
}
16911725
}
16921726
else
16931727
{
1694-
return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCertificateLocation, certificateLocation, certificatePath, validLocations[0], validLocations[1], @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH);
1728+
Debug.Assert(validLocations.Length == 1);
1729+
if (isSystemOp)
1730+
{
1731+
return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCertificateLocationSysErr_Unix, certificateLocation, certificatePath, validLocations[0], @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH);
1732+
}
1733+
else
1734+
{
1735+
return ADP.Argument(StringsHelper.GetString(Strings.TCE_InvalidCertificateLocation_Unix, certificateLocation, certificatePath, validLocations[0], @"/"), TdsEnums.TCE_PARAM_MASTERKEY_PATH);
1736+
}
16951737
}
16961738
}
16971739

0 commit comments

Comments
 (0)