public void ImportExistingCertificateShouldNotOverwriteExistingPrivateKeyRights(string sampleCertificateId, StoreLocation storeLocation, string storeName) { var sampleCertificate = SampleCertificate.SampleCertificates[sampleCertificateId]; sampleCertificate.EnsureCertificateNotInStore(storeName, storeLocation); WindowsX509CertificateStore.ImportCertificateToStore( Convert.FromBase64String(sampleCertificate.Base64Bytes()), sampleCertificate.Password, storeLocation, storeName, sampleCertificate.HasPrivateKey); WindowsX509CertificateStore.AddPrivateKeyAccessRules(sampleCertificate.Thumbprint, storeLocation, storeName, new List <PrivateKeyAccessRule> { new PrivateKeyAccessRule("BUILTIN\\Users", PrivateKeyAccess.FullControl) }); WindowsX509CertificateStore.ImportCertificateToStore( Convert.FromBase64String(sampleCertificate.Base64Bytes()), sampleCertificate.Password, storeLocation, storeName, sampleCertificate.HasPrivateKey); var privateKeySecurity = WindowsX509CertificateStore.GetPrivateKeySecurity(sampleCertificate.Thumbprint, storeLocation, storeName); AssertHasPrivateKeyRights(privateKeySecurity, "BUILTIN\\Users", CryptoKeyRights.GenericAll); sampleCertificate.EnsureCertificateNotInStore(storeName, storeLocation); }
void ImportCertificate(CalamariVariableDictionary variables) { var certificateVariable = GetMandatoryVariable(variables, SpecialVariables.Action.Certificate.CertificateVariable); var pfxBytes = Convert.FromBase64String(GetMandatoryVariable(variables, $"{certificateVariable}.{SpecialVariables.Certificate.Properties.Pfx}")); var password = variables.Get($"{certificateVariable}.{SpecialVariables.Certificate.Properties.Password}"); var thumbprint = variables.Get($"{certificateVariable}.{SpecialVariables.Certificate.Properties.Thumbprint}"); var storeName = GetMandatoryVariable(variables, SpecialVariables.Action.Certificate.StoreName); var privateKeyExportable = variables.GetFlag(SpecialVariables.Action.Certificate.PrivateKeyExportable, false); // Either a store-location (LocalMachine or CurrentUser) or a user can be supplied StoreLocation storeLocation; var locationSpecified = Enum.TryParse(variables.Get(SpecialVariables.Action.Certificate.StoreLocation), out storeLocation); ValidateStore(locationSpecified ? (StoreLocation?)storeLocation : null, storeName); try { if (locationSpecified) { Log.Info( $"Importing certificate '{variables.Get($"{certificateVariable}.{SpecialVariables.Certificate.Properties.Subject}")}' with thumbprint '{thumbprint}' into store '{storeLocation}\\{storeName}'"); WindowsX509CertificateStore.ImportCertificateToStore(pfxBytes, password, storeLocation, storeName, privateKeyExportable); if (storeLocation == StoreLocation.LocalMachine) { // Set private-key access var privateKeyAccessRules = GetPrivateKeyAccessRules(variables); if (privateKeyAccessRules.Any()) { WindowsX509CertificateStore.AddPrivateKeyAccessRules(thumbprint, storeLocation, storeName, privateKeyAccessRules); } } } else // Import into a specific user's store { var storeUser = variables.Get(SpecialVariables.Action.Certificate.StoreUser); if (string.IsNullOrWhiteSpace(storeUser)) { throw new CommandException( $"Either '{SpecialVariables.Action.Certificate.StoreLocation}' or '{SpecialVariables.Action.Certificate.StoreUser}' must be supplied"); } Log.Info( $"Importing certificate '{variables.Get($"{certificateVariable}.{SpecialVariables.Certificate.Properties.Subject}")}' with thumbprint '{thumbprint}' into store '{storeName}' for user '{storeUser}'"); WindowsX509CertificateStore.ImportCertificateToStore(pfxBytes, password, storeUser, storeName, privateKeyExportable); } } catch (Exception) { Log.Error("There was an error importing the certificate into the store"); throw; } }
void RemoveChainCertificatesFromStore(X509Store rootAuthorityStore, X509Store intermediateAuthorityStore, string rootAuthorityThumbprint, string intermediateAuthorityThumbprint) { WindowsX509CertificateStore.RemoveCertificateFromStore(rootAuthorityThumbprint, StoreLocation.LocalMachine, rootAuthorityStore.Name); if (!string.IsNullOrEmpty(intermediateAuthorityThumbprint)) { WindowsX509CertificateStore.RemoveCertificateFromStore(intermediateAuthorityThumbprint, StoreLocation.LocalMachine, intermediateAuthorityStore.Name); } }
private void EnsureCertificateNotInStore(X509Store store) { var certificates = store.Certificates.Find(X509FindType.FindByThumbprint, Thumbprint, false); if (certificates.Count == 0) { return; } WindowsX509CertificateStore.RemoveCertificateFromStore(Thumbprint, store.Location, store.Name); }
public void CanImportCertificateForUser() { // This test cheats a little bit, using the current user var user = System.Security.Principal.WindowsIdentity.GetCurrent().Name; var storeName = "My"; var sampleCertificate = SampleCertificate.CapiWithPrivateKey; sampleCertificate.EnsureCertificateNotInStore(storeName, StoreLocation.CurrentUser); WindowsX509CertificateStore.ImportCertificateToStore(Convert.FromBase64String(sampleCertificate.Base64Bytes()), sampleCertificate.Password, user, storeName, sampleCertificate.HasPrivateKey); sampleCertificate.AssertCertificateIsInStore(storeName, StoreLocation.CurrentUser); sampleCertificate.EnsureCertificateNotInStore(storeName, StoreLocation.CurrentUser); }
public void CanImportCertificateChain(string sampleCertificateId, string intermediateAuthorityThumbprint, string rootAuthorityThumbprint, StoreLocation storeLocation, string storeName) { var sampleCertificate = SampleCertificate.SampleCertificates[sampleCertificateId]; // intermediate and root authority certificates are always imported to LocalMachine var rootAuthorityStore = new X509Store(StoreName.Root, StoreLocation.LocalMachine); rootAuthorityStore.Open(OpenFlags.ReadWrite); var intermediateAuthorityStore = new X509Store(StoreName.CertificateAuthority, StoreLocation.LocalMachine); intermediateAuthorityStore.Open(OpenFlags.ReadWrite); WindowsX509CertificateStore.RemoveCertificateFromStore(rootAuthorityThumbprint, StoreLocation.LocalMachine, rootAuthorityStore.Name); if (!string.IsNullOrEmpty(intermediateAuthorityThumbprint)) { WindowsX509CertificateStore.RemoveCertificateFromStore(intermediateAuthorityThumbprint, StoreLocation.LocalMachine, intermediateAuthorityStore.Name); } sampleCertificate.EnsureCertificateNotInStore(storeName, storeLocation); WindowsX509CertificateStore.ImportCertificateToStore(Convert.FromBase64String(sampleCertificate.Base64Bytes()), sampleCertificate.Password, storeLocation, storeName, sampleCertificate.HasPrivateKey); sampleCertificate.AssertCertificateIsInStore(storeName, storeLocation); // Assert chain certificates were imported if (!string.IsNullOrEmpty(intermediateAuthorityThumbprint)) { AssertCertificateInStore(intermediateAuthorityStore, intermediateAuthorityThumbprint); } AssertCertificateInStore(rootAuthorityStore, rootAuthorityThumbprint); var certificate = sampleCertificate.GetCertificateFromStore(storeName, storeLocation); Assert.True(certificate.HasPrivateKey); sampleCertificate.EnsureCertificateNotInStore(storeName, storeLocation); WindowsX509CertificateStore.RemoveCertificateFromStore(rootAuthorityThumbprint, StoreLocation.LocalMachine, rootAuthorityStore.Name); if (!string.IsNullOrEmpty(intermediateAuthorityThumbprint)) { WindowsX509CertificateStore.RemoveCertificateFromStore(intermediateAuthorityThumbprint, StoreLocation.LocalMachine, intermediateAuthorityStore.Name); } }
static string FindCertificateInLocalMachineStore(string thumbprint) { foreach (var storeName in WindowsX509CertificateStore.GetStoreNames(StoreLocation.LocalMachine)) { var store = new X509Store(storeName, StoreLocation.LocalMachine); store.Open(OpenFlags.ReadOnly); var found = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false); if (found.Count != 0 && found[0].HasPrivateKey) { return(storeName); } store.Close(); } return(null); }
static string AddCertificateToStore(VariableDictionary variables, string certificateVariable, StoreLocation storeLocation, string storeName) { var pfxBytes = Convert.FromBase64String(variables.Get($"{certificateVariable}.{SpecialVariables.Certificate.Properties.Pfx}")); var password = variables.Get($"{certificateVariable}.{SpecialVariables.Certificate.Properties.Password}"); var subject = variables.Get($"{certificateVariable}.{SpecialVariables.Certificate.Properties.Subject}"); Log.Info($"Adding certificate '{subject}' into Cert:\\{storeLocation}\\{storeName}"); try { WindowsX509CertificateStore.ImportCertificateToStore(pfxBytes, password, storeLocation, storeName, true); return(storeName); } catch (Exception) { Log.Error("Exception while attempting to add certificate to store"); throw; } }
static string AddCertificateToLocalMachineStore(IVariables variables, string certificateVariable) { var pfxBytes = Convert.FromBase64String(variables.Get($"{certificateVariable}.{CertificateVariables.Properties.Pfx}")); var password = variables.Get($"{certificateVariable}.{CertificateVariables.Properties.Password}"); var subject = variables.Get($"{certificateVariable}.{CertificateVariables.Properties.Subject}"); Log.Info($"Adding certificate '{subject}' into Cert:\\LocalMachine\\My"); try { WindowsX509CertificateStore.ImportCertificateToStore(pfxBytes, password, StoreLocation.LocalMachine, "My", true); return("My"); } catch (Exception) { Log.Error("Exception while attempting to add certificate to store"); throw; } }
public void CanImportCertificate(string sampleCertificateId, StoreLocation storeLocation, string storeName) { var sampleCertificate = SampleCertificate.SampleCertificates[sampleCertificateId]; sampleCertificate.EnsureCertificateNotInStore(storeName, storeLocation); WindowsX509CertificateStore.ImportCertificateToStore(Convert.FromBase64String(sampleCertificate.Base64Bytes()), sampleCertificate.Password, storeLocation, storeName, sampleCertificate.HasPrivateKey); sampleCertificate.AssertCertificateIsInStore(storeName, storeLocation); if (sampleCertificate.HasPrivateKey) { var certificate = sampleCertificate.GetCertificateFromStore(storeName, storeLocation); Assert.True(certificate.HasPrivateKey); } sampleCertificate.EnsureCertificateNotInStore(storeName, storeLocation); }
static void EnsureApplicationPoolHasCertificatePrivateKeyAccess(VariableDictionary variables) { foreach (var binding in GetEnabledBindings(variables)) { string certificateVariable = binding.certificateVariable; if (string.IsNullOrWhiteSpace(certificateVariable)) { continue; } var thumbprint = variables.Get($"{certificateVariable}.{SpecialVariables.Certificate.Properties.Thumbprint}"); var privateKeyAccess = CreatePrivateKeyAccessForApplicationPoolAccount(variables); // The store-name variable was set by IisWebSiteBeforePostDeploy var storeName = variables.Get(SpecialVariables.Action.IisWebSite.Output.CertificateStoreName); WindowsX509CertificateStore.AddPrivateKeyAccessRules(thumbprint, StoreLocation.LocalMachine, storeName, new List <PrivateKeyAccessRule> { privateKeyAccess }); } }
/// <summary> /// SF allows you to provide an override location for the storeLocation and storeName, so this method can optionally /// check for the certificate thumbprint in the given storeLocation/storeName. /// </summary> /// <param name="thumbprint"></param> /// <param name="storeLocation"></param> /// <param name="storeNameOverride"></param> /// <returns></returns> static string FindCertificateInStore(string thumbprint, StoreLocation storeLocation, string storeNameOverride) { foreach (var storeName in WindowsX509CertificateStore.GetStoreNames(storeLocation)) { if (!string.IsNullOrEmpty(storeNameOverride) && storeName.Equals(storeNameOverride, StringComparison.InvariantCultureIgnoreCase)) { continue; } //Log.Verbose($"Trying to find certificate with thumbprint '{thumbprint}' in Cert:\\{storeLocation}\\{storeName}"); var store = new X509Store(storeName, storeLocation); store.Open(OpenFlags.ReadOnly); var found = store.Certificates.Find(X509FindType.FindByThumbprint, thumbprint, false); if (found.Count != 0 && found[0].HasPrivateKey) { return(storeName); } store.Close(); } return(null); }
public void SafeForConcurrentOperations() { var maxTimeAllowedForTest = TimeSpan.FromSeconds(20); var sw = Stopwatch.StartNew(); try { using (var cts = new CancellationTokenSource(maxTimeAllowedForTest)) { var cancellationToken = cts.Token; var sampleCertificate = SampleCertificate.SampleCertificates[SampleCertificate.CngPrivateKeyId]; var numThreads = 20; var numIterationsPerThread = 1; var exceptions = new BlockingCollection <Exception>(); void Log(string message) => Console.WriteLine($"{sw.Elapsed} {Thread.CurrentThread.Name}: {message}"); WindowsX509CertificateStore.ImportCertificateToStore( Convert.FromBase64String(sampleCertificate.Base64Bytes()), sampleCertificate.Password, StoreLocation.LocalMachine, "My", sampleCertificate.HasPrivateKey); CountdownEvent allThreadsReady = null; CountdownEvent allThreadsFinished = null; ManualResetEventSlim goForIt = new ManualResetEventSlim(false); Thread[] CreateThreads(int number, string name, Action action) => Enumerable.Range(0, number) .Select(i => new Thread(() => { allThreadsReady.Signal(); goForIt.Wait(cancellationToken); for (int j = 0; j < numIterationsPerThread; j++) { try { Log($"{name} {j}"); action(); } catch (Exception e) { Log(e.ToString()); exceptions.Add(e); } } allThreadsFinished.Signal(); }) { Name = $"{name}#{i}" }).ToArray(); var threads = CreateThreads(numThreads, "ImportCertificateToStore", () => { WindowsX509CertificateStore.ImportCertificateToStore( Convert.FromBase64String(sampleCertificate.Base64Bytes()), sampleCertificate.Password, StoreLocation.LocalMachine, "My", sampleCertificate.HasPrivateKey); }) .Concat(CreateThreads(numThreads, "AddPrivateKeyAccessRules", () => { WindowsX509CertificateStore.AddPrivateKeyAccessRules( sampleCertificate.Thumbprint, StoreLocation.LocalMachine, "My", new List <PrivateKeyAccessRule> { new PrivateKeyAccessRule("BUILTIN\\Users", PrivateKeyAccess.FullControl) }); })) .Concat(CreateThreads(numThreads, "GetPrivateKeySecurity", () => { var unused = WindowsX509CertificateStore.GetPrivateKeySecurity( sampleCertificate.Thumbprint, StoreLocation.LocalMachine, "My"); })).ToArray(); allThreadsReady = new CountdownEvent(threads.Length); allThreadsFinished = new CountdownEvent(threads.Length); foreach (var thread in threads) { thread.Start(); } allThreadsReady.Wait(cancellationToken); goForIt.Set(); allThreadsFinished.Wait(cancellationToken); foreach (var thread in threads) { Log($"Waiting for {thread.Name} to join..."); if (!thread.Join(TimeSpan.FromSeconds(1))) { Log($"Aborting {thread.Name}"); thread.Abort(); } } sw.Stop(); sampleCertificate.EnsureCertificateNotInStore("My", StoreLocation.LocalMachine); if (exceptions.Any()) { throw new AssertionException( $"The following exceptions were thrown during the test causing it to fail:{Environment.NewLine}{string.Join($"{Environment.NewLine}{new string('=', 80)}", exceptions.GroupBy(ex => ex.Message).Select(g => g.First().ToString()))}"); } if (sw.Elapsed > maxTimeAllowedForTest) { throw new TimeoutException( $"This test exceeded the {maxTimeAllowedForTest} allowed for this test to complete."); } } } catch (OperationCanceledException) { throw new TimeoutException($"This test took longer than {maxTimeAllowedForTest} to run"); } }