Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Add support for querying remote certificate store for deploying HTTPS…

… bindings to a remote machine
  • Loading branch information...
commit e7e6edbf5915626b0951237571ad4dd8c246fa6b 1 parent eafb0ee
@laazyj authored
View
4 product/dropkick.tests/Tasks/Iis/Iis7TaskSpecs.cs
@@ -29,6 +29,7 @@ public void It_should_not_return_any_errors_from_task_execution()
public override void Context()
{
+ _store = new CertificateStore(WebServerName);
Task = new Iis7Task { WebsiteName = TestWebSiteName, ServerName = WebServerName };
}
@@ -60,7 +61,7 @@ protected void AssertSiteBinding(string protocol, int port, string certificateTh
if (certificateThumbprint != null)
{
- Assert.AreEqual(CertificateStoreUtility.GetCertificateHashForThumbprint(certificateThumbprint), binding.CertificateHash);
+ Assert.AreEqual(_store.GetCertificateHashForThumbprint(certificateThumbprint), binding.CertificateHash);
}
}
}
@@ -102,6 +103,7 @@ protected void WaitForIis()
protected Iis7Task Task;
protected DeploymentResult ExecutionResult;
protected DeploymentResult VerificationResult;
+ CertificateStore _store;
protected const string TestWebSiteName = "_DropKickTest_4789";
protected const string WebServerName = "localhost";
}
View
31 product/dropkick.tests/Tasks/Security/Certificate/CertificateStoreUtilitySpecs.cs
@@ -1,6 +1,4 @@
-using System;
-using System.Security.Cryptography.X509Certificates;
-using NUnit.Framework;
+using NUnit.Framework;
using dropkick.Tasks.Security.Certificate;
namespace dropkick.tests.Tasks.Security.Certificate
@@ -21,13 +19,38 @@ public void It_should_return_the_correct_hash()
public override void Context()
{
+ _store = new CertificateStore();
}
public override void Because()
{
- _certHash = CertificateStoreUtility.GetCertificateHashForThumbprint("b1 76 8f 34 6c e4 14 1a ca b9 bd d9 84 7e 32 d9 8f 13 73 42");
+ _certHash = _store.GetCertificateHashForThumbprint("b1 76 8f 34 6c e4 14 1a ca b9 bd d9 84 7e 32 d9 8f 13 73 42");
}
byte[] _certHash;
+ CertificateStore _store;
+ }
+
+ [Category("Integration")]
+ public class When_querying_certificate_store_on_a_remote_machine : TinySpec
+ {
+ [Fact]
+ public void It_should_find_the_certificate()
+ {
+ Assert.IsNotNull(_certHash);
+ }
+
+ public override void Context()
+ {
+ _store = new CertificateStore("APP01.tron.espares.co.uk");
+ }
+
+ public override void Because()
+ {
+ _certHash = _store.GetCertificateHashForThumbprint("e833d41450b1f4bbf69467fd9906d373a699d239");
+ }
+
+ byte[] _certHash;
+ CertificateStore _store;
}
}
View
93 product/dropkick/Tasks/Iis/Iis7Task.cs
@@ -40,6 +40,7 @@ public class Iis7Task : BaseIisTask
public string ManagedRuntimeVersion { get; set; }
readonly Path _path = new DotNetPath();
+ CertificateStore _certificateStore;
public override int VersionNumber
{
@@ -59,60 +60,74 @@ public override DeploymentResult VerifyCanRun()
IisUtility.CheckForIis7(result);
- LogIis("WebSite: {0}", WebsiteName);
- LogIis("Application Pool: {0}", AppPoolName);
- var iisManager = ServerManager.OpenRemote(ServerName);
- CheckForSiteAndVDirExistance(DoesSiteExist, () => DoesVirtualDirectoryExist(GetSite(iisManager, WebsiteName)), result);
- checkForSiteBindingConflict(iisManager, WebsiteName, Bindings);
- checkCertificatesExist(Bindings.Where(x => !String.IsNullOrEmpty(x.CertificateThumbPrint)).Select(x => x.CertificateThumbPrint), result);
- checkHttpsBindingsHaveCertificate(result);
-
- if (UseClassicPipeline) result.AddAlert("The Application Pool '{0}' will be set to Classic Pipeline Mode", AppPoolName);
+ setupCertificateStore();
+ using (var iisManager = ServerManager.OpenRemote(ServerName))
+ {
+ CheckForSiteAndVDirExistance(DoesSiteExist,
+ () => DoesVirtualDirectoryExist(GetSite(iisManager, WebsiteName)), result);
+ checkForSiteBindingConflict(iisManager, WebsiteName, Bindings);
+ checkCertificatesExist(Bindings.Where(x =>
+ !String.IsNullOrEmpty(x.CertificateThumbPrint)).Select(x => x.CertificateThumbPrint), result);
+ checkHttpsBindingsHaveCertificate(result);
+
+ if (UseClassicPipeline) result.AddAlert("The Application Pool '{0}' will be set to Classic Pipeline Mode", AppPoolName);
+ }
return result;
}
+ void setupCertificateStore()
+ {
+ _certificateStore = new CertificateStore(ServerName);
+ }
+
void checkHttpsBindingsHaveCertificate(DeploymentResult result)
{
foreach (var invalidBinding in Bindings.Where(x => x.Protocol == "https" && String.IsNullOrEmpty(x.CertificateThumbPrint)))
result.AddError("Cannot bind https to port '{0}' as no certificate thumbprint was specified.".FormatWith(invalidBinding.Port));
}
- static void checkCertificatesExist(IEnumerable<string> certificateThumbprints, DeploymentResult result)
+ void checkCertificatesExist(IEnumerable<string> certificateThumbprints, DeploymentResult result)
{
- foreach (var thumbprint in certificateThumbprints.Where(thumbprint => !CertificateStoreUtility.CertificateExists(thumbprint)))
+ foreach (var thumbprint in certificateThumbprints.Where(thumbprint => !_certificateStore.CertificateExists(thumbprint)))
result.AddError("No certificate found with thumbprint '{0}'".FormatWith(thumbprint));
}
public override DeploymentResult Execute()
{
var result = new DeploymentResult();
- var iisManager = ServerManager.OpenRemote(ServerName);
- buildApplicationPool(iisManager, result);
-
- if (!DoesSiteExist(result)) createWebSite(iisManager, WebsiteName);
-
- var site = GetSite(iisManager, WebsiteName);
- updateSiteBindings(site);
- buildVirtualDirectory(site, result);
-
- try
- {
- iisManager.CommitChanges();
- result.AddGood("Virtual Directory '{0}' was created/updated successfully.", VirtualDirectoryPath ?? "/");
- }
- catch (COMException ex)
- {
- if (ProcessModelIdentityType == ProcessModelIdentityType.SpecificUser) throw new DeploymentException("An exception occurred trying to apply deployment changes. If you are attempting to set the IIS " +
- "Process Model's identity to a specific user then ensure that you are running DropKick with elevated privileges, or UAC is disabled.", ex);
- throw;
- }
- LogCoarseGrain("[iis7] {0}", Name);
-
+ setupCertificateStore();
+ using (var iisManager = ServerManager.OpenRemote(ServerName))
+ {
+ buildApplicationPool(iisManager, result);
+
+ if (!DoesSiteExist(result)) createWebSite(iisManager, WebsiteName);
+
+ var site = GetSite(iisManager, WebsiteName);
+ updateSiteBindings(site, result);
+ buildVirtualDirectory(site, result);
+
+ try
+ {
+ iisManager.CommitChanges();
+ result.AddGood("Virtual Directory '{0}' was created/updated successfully.",
+ VirtualDirectoryPath ?? "/");
+ }
+ catch (COMException ex)
+ {
+ if (ProcessModelIdentityType == ProcessModelIdentityType.SpecificUser)
+ throw new DeploymentException(
+ "An exception occurred trying to apply deployment changes. If you are attempting to set the IIS " +
+ "Process Model's identity to a specific user then ensure that you are running DropKick with elevated privileges, or UAC is disabled.",
+ ex);
+ throw;
+ }
+ LogCoarseGrain("[iis7] {0}", Name);
+ }
return result;
}
- void updateSiteBindings(Site site)
+ void updateSiteBindings(Site site, DeploymentResult result)
{
// https bindings certificates cannot be compared or updated, these bindings must be recreated each time.
var httpsBindings = site.Bindings.Where(x => x.Protocol == "https").ToArray();
@@ -127,6 +142,7 @@ void updateSiteBindings(Site site)
{
if (newBinding.Protocol != "https") site.Bindings.Add(getBindingInformation(newBinding), newBinding.Protocol);
else site.Bindings.Add(getBindingInformation(newBinding), getCertificateHashFor(newBinding), "MY");
+ LogIis("[iis7] Added binding for {0}://*:{1}", newBinding.Protocol, newBinding.Port);
}
}
@@ -134,10 +150,13 @@ void updateSiteBindings(Site site)
{
var existingBinding = site.Bindings[i];
if (!Bindings.Any(x => x.Protocol == existingBinding.Protocol && x.Port == existingBinding.EndPoint.Port))
+ {
site.Bindings.Remove(existingBinding);
+ LogIis("[iis7] Removed binding for {0}://*:{1}", existingBinding.Protocol, existingBinding.EndPoint.Port);
+ }
}
- LogIis("[iis7] Updating bindings for website '{0}'", WebsiteName);
+ result.AddGood("Updated bindings for website '{0}'", WebsiteName);
}
public bool DoesSiteExist(DeploymentResult result)
@@ -170,14 +189,14 @@ void createWebSite(ServerManager iisManager, string websiteName)
: iisManager.Sites.Add(WebsiteName, getBindingInformation(firstBinding), PathOnServer,
getCertificateHashFor(firstBinding));
- LogIis("[iis7] Created website '{0}'", WebsiteName);
+ LogIis("[iis7] Created website '{0}' with binding for {1}://*:{2}", WebsiteName, firstBinding.Protocol, firstBinding.Port);
}
byte[] getCertificateHashFor(IisSiteBinding binding)
{
return binding.CertificateThumbPrint == null
? new byte[0]
- : CertificateStoreUtility.GetCertificateHashForThumbprint(binding.CertificateThumbPrint);
+ : _certificateStore.GetCertificateHashForThumbprint(binding.CertificateThumbPrint);
}
static string getBindingInformation(IisSiteBinding binding)
View
27 product/dropkick/Tasks/Security/Certificate/CertificateStoreUtility.cs
@@ -3,9 +3,21 @@
namespace dropkick.Tasks.Security.Certificate
{
- public static class CertificateStoreUtility
+ public class CertificateStore
{
- public static byte[] GetCertificateHashForThumbprint(string certificateThumbprint)
+ readonly X509Store _store;
+
+ public CertificateStore()
+ {
+ _store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
+ }
+
+ public CertificateStore(string machine)
+ {
+ _store = new X509Store(@"\\{0}\MY".FormatWith(machine), StoreLocation.LocalMachine);
+ }
+
+ public byte[] GetCertificateHashForThumbprint(string certificateThumbprint)
{
var certificate = getCertificateFromThumbprint(certificateThumbprint);
if (certificate.Count == 0)
@@ -16,23 +28,22 @@ public static byte[] GetCertificateHashForThumbprint(string certificateThumbprin
return certificate[0].GetCertHash();
}
- public static bool CertificateExists(string thumbprint)
+ public bool CertificateExists(string thumbprint)
{
return getCertificateFromThumbprint(thumbprint).Count > 0;
}
- static X509Certificate2Collection getCertificateFromThumbprint(string certificateThumbprint)
+ X509Certificate2Collection getCertificateFromThumbprint(string certificateThumbprint)
{
- var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
- store.Open(OpenFlags.OpenExistingOnly);
+ _store.Open(OpenFlags.OpenExistingOnly);
try
{
- var certificate = store.Certificates.Find(X509FindType.FindByThumbprint, certificateThumbprint, false);
+ var certificate = _store.Certificates.Find(X509FindType.FindByThumbprint, certificateThumbprint, false);
return certificate;
}
finally
{
- store.Close();
+ _store.Close();
}
}
Please sign in to comment.
Something went wrong with that request. Please try again.