-
Notifications
You must be signed in to change notification settings - Fork 110
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
Remove as much of the WINDOWS_CERT compiler directives as possible #1352
base: main
Are you sure you want to change the base?
Conversation
@@ -81,7 +81,7 @@ protected virtual int Run(string[] args) | |||
} | |||
catch (Exception ex) | |||
{ | |||
return ConsoleFormatter.PrintError(ConsoleLog.Instance, ex); | |||
return ConsoleFormatter.PrintError(Log, ex); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change allows us to capture the output properly when debugging tests
@@ -115,6 +114,8 @@ public static byte[] GetCspPrivateKeySecurity(SafeCspHandle cspHandle) | |||
return buffer; | |||
} | |||
|
|||
// At the moment these models are not in the Calamari Solution. This is the next step. | |||
#if WINDOWS_CERTIFICATE_STORE_SUPPORT | |||
public static byte[] GetCngPrivateKeySecurity(SafeNCryptKeyHandle hObject) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The SafeNCryptKeyHandle
structures are not currently defined in the Octopus solution like some of the others, and so this will need to be introduced as netcore does not have access to them from mscorlib like natframework does.
To keep the changes in multiple stages, this will be introduced in a followup PR.
As such we can generally still assume that for the sake of this PR, most of the cert capabilities are fundamentally still only available in netfx, we are just starting to expose and test some of the classes in netcore.
@@ -69,14 +68,7 @@ internal static extern bool CryptAcquireCertificatePrivateKey(SafeCertContextHan | |||
[Out] out int dwKeySpec, | |||
[Out, MarshalAs(UnmanagedType.Bool)] out bool pfCallerFreeProvOrNCryptKey); | |||
|
|||
[DllImport("Crypt32.dll", SetLastError = true)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shuffled down to put between the other unmanaged invocations that are currently only available in netfx for this PR
} | ||
|
||
// This should only be used in tests | ||
public WindowsX509CertificateStore(): this(ConsoleLog.Instance) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want to pass through the ILog
to help with tests looking for specific output, but other logs dont care and so this default constructor makes it a little easier for those scenarios.
|
||
store.Close(); | ||
} | ||
} | ||
|
||
public CryptoKeySecurity GetPrivateKeySecurity(string thumbprint, StoreLocation storeLocation, string storeName) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Extracted out into the CryptoKeySecurityAccessRules
class so that we can more cleanly control the differences between netcore and netfx
using Calamari.Tests.Helpers; | ||
using Calamari.Tests.Helpers.Certificates; | ||
using NUnit.Framework; | ||
using Octostache; | ||
|
||
namespace Calamari.Tests.Fixtures.Certificates | ||
{ | ||
[Category(TestCategory.CompatibleOS.OnlyWindows)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Previously this whole test wouldnt even exist in netcore, now netcore can run some of these tests so long as its on windows
@@ -53,12 +54,15 @@ public void AddingCertToStore_AddsCert() | |||
cert.EnsureCertificateNotInStore(storeName, certificateStoreLocation); | |||
} | |||
|
|||
#if WINDOWS_CERTIFICATE_STORE_SUPPORT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test still relies on some of the capabilities not yet available to netcore (see above), it will be exposed again in a later PR
@@ -1,6 +1,4 @@ | |||
#if WINDOWS_CERTIFICATE_STORE_SUPPORT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A bunch of the file changes are just this, removing the #if WINDOWS_CERTIFICATE_STORE_SUPPORT
compiler directive, meaning it compiles into netcore, even if it shouldnt actually be getting invoked by anything (since the Calamari.netfx
flavour is used for anything on Windows that would have the IIS/WindowsCert variables provided)
namespace Calamari.Integration.Certificates | ||
{ | ||
#if WINDOWS_CERTIFICATE_STORE_SUPPORT | ||
public static class CryptoKeySecurityAccessRules |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This class is just the extraction of a bunch of CryptoKey logic that was moved out of WindowsX509CertificateStore
that cannot currently compile in netcore. The functionality is essentially unchanged, with the addition of a compiler directive returning the "failing" implementation to be used by netcore (not actually used-used, but compiled for)
return; | ||
} | ||
|
||
throw new CryptographicException(error); | ||
} | ||
|
||
Log.Info($"Imported certificate '{subjectName}' into store '{storeName}'"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of these static Log
methods made testing using the in-process Calamari fail (as opposed to many tests which actually invoke Calamari.exe
and make debugging impossible)
@@ -406,116 +389,6 @@ static IList<SafeCertContextHandle> GetCertificatesFromPfx(byte[] pfxBytes, stri | |||
} | |||
} | |||
|
|||
static void AddPrivateKeyAccessRules(ICollection<PrivateKeyAccessRule> accessRules, SafeCertContextHandle certificate) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved out to CryptoKeySecurityAccessRules
CalamariResult Invoke(VariableDictionary variables) | ||
{ | ||
using (var variablesFile = new TemporaryFile(Path.GetTempFileName())) | ||
{ | ||
variables.Save(variablesFile.FilePath); | ||
return Invoke(Calamari() | ||
return InvokeInProcess(Calamari() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This simply runs the test in the same process as the test harness, making debugging possible.
I'd like to move all Calamari tests to this format now that we have a bit more of a handle on the different runtimes that we are actually running
@@ -221,12 +227,22 @@ public void ImportExistingCertificateShouldNotOverwriteExistingPrivateKeyRights( | |||
Convert.FromBase64String(sampleCertificate.Base64Bytes()), sampleCertificate.Password, | |||
storeLocation, storeName, sampleCertificate.HasPrivateKey); | |||
|
|||
var privateKeySecurity = new WindowsX509CertificateStore().GetPrivateKeySecurity(sampleCertificate.Thumbprint, | |||
storeLocation, storeName); | |||
var privateKeySecurity = CryptoKeySecurityAccessRules.GetPrivateKeySecurity(sampleCertificate.Thumbprint, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that the CryptoKeySecurityAccessRule
method is extracted, we can actually consolidate some of the test assertions that check for certificate access rules (See Below)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Background
This PR essentially moves away a bunch of
#if WINDOWS_CERTIFICATE_STORE_SUPPORT
compiler directives to pinpoint the code that is currently (as of this PR) unable to be compiled for .netcore.The follow up PR takes the next leap and attempts to provide capabilities for netcore to involve the few places that are not supported as discovered by these changes.
Whats Changed
What this turns out to be is essentially just the code that deals with assigning access to windows certificates. Although now then exposes in netcore classes that uses unmanaged code (windows dlls etc), these code paths should only ever exist on tasks running on windows machines (or they would have otherwise been failing in the past anyway, who's trying to run IIS steps on linux?)
How to review
Hopefully just a sanity check, nothing functionally should really change for users.