Skip to content
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

Implement support for enabling SSL #365

Merged
merged 1 commit into from Feb 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
54 changes: 52 additions & 2 deletions nvQuickSite/Controllers/IISController.cs
Expand Up @@ -22,6 +22,7 @@ namespace nvQuickSite.Controllers
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Cryptography.X509Certificates;

using Microsoft.Web.Administration;
using nvQuickSite.Controllers.Exceptions;
Expand All @@ -39,7 +40,8 @@ public static class IISController
/// <param name="installFolder">The path to the hosting folder for the site.</param>
/// <param name="useSiteSpecificAppPool">A value indicating whether to use a site specific App Pool.</param>
/// <param name="deleteSiteIfExists">If true will delete and recreate the site.</param>
internal static void CreateSite(string siteName, string installFolder, bool useSiteSpecificAppPool, bool deleteSiteIfExists)
/// <param name="certificate">The certificate to use for the site.</param>
internal static void CreateSite(string siteName, string installFolder, bool useSiteSpecificAppPool, bool deleteSiteIfExists, X509Certificate2 certificate = null)
{
Log.Logger.Information("Creating site {siteName} in {installFolder}", siteName, installFolder);
if (SiteExists(siteName, deleteSiteIfExists))
Expand All @@ -51,10 +53,18 @@ internal static void CreateSite(string siteName, string installFolder, bool useS
try
{
var bindingInfo = "*:80:" + siteName;
var protocol = "http";

using (ServerManager iisManager = new ServerManager())
{
Site site = iisManager.Sites.Add(siteName, "http", bindingInfo, installFolder + "\\Website");
Site site = iisManager.Sites.Add(siteName, protocol, bindingInfo, installFolder + "\\Website");
if (certificate != null)
{
bindingInfo = "*:443:" + siteName;
protocol = "https";
}

site.Bindings.Add(bindingInfo, protocol);
site.TraceFailedRequestsLogging.Enabled = true;
site.TraceFailedRequestsLogging.Directory = installFolder + "\\Logs";
site.LogFile.Directory = installFolder + "\\Logs" + "\\W3svc" + site.Id.ToString(CultureInfo.InvariantCulture);
Expand Down Expand Up @@ -152,6 +162,46 @@ internal static void DeleteAppPool(string appPoolName, IProgress<int> progress)
}
}

/// <summary>
/// Gets a list of SSL certificates available for use within IIS.
/// </summary>
/// <returns>An enumeration of SSL certificates.</returns>
internal static List<X509Certificate2> GetSslCertificates()
{
Log.Logger.Information("Getting a list of SSL certificates");
var certificates = new List<X509Certificate2>();

var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
try
{
store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);

foreach (var certificate in store.Certificates)
{
foreach (var extension in certificate.Extensions)
{
if (extension.Oid.FriendlyName == "Enhanced Key Usage" && extension is X509EnhancedKeyUsageExtension enhancedKeyUsageExtension)
{
foreach (var item in enhancedKeyUsageExtension.EnhancedKeyUsages)
{
if (item.FriendlyName == "Server Authentication")
{
certificates.Add(certificate);
}
}
}
}
}

Log.Logger.Debug("Found the following SSL certificates {@certicates}", certificates);
return certificates;
}
finally
{
store.Close();
}
}

/// <summary>
/// Gets a list of IIS sites.
/// </summary>
Expand Down
4 changes: 2 additions & 2 deletions nvQuickSite/Properties/AssemblyInfo.cs
Expand Up @@ -49,6 +49,6 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.2.0")]
[assembly: AssemblyFileVersion("2.2.0")]
[assembly: AssemblyVersion("2.3.0")]
[assembly: AssemblyFileVersion("2.3.0")]
[assembly: NeutralResourcesLanguage("en")]
26 changes: 25 additions & 1 deletion nvQuickSite/Properties/Settings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions nvQuickSite/Properties/Settings.settings
Expand Up @@ -47,5 +47,11 @@
<Setting Name="EnableLocalPackageInstall" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="EnableSsl" Type="System.Boolean" Scope="User">
<Value Profile="(Default)">False</Value>
</Setting>
<Setting Name="CertificateFriendlyName" Type="System.String" Scope="User">
<Value Profile="(Default)" />
</Setting>
</Settings>
</SettingsFile>
34 changes: 31 additions & 3 deletions nvQuickSite/Start.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

45 changes: 43 additions & 2 deletions nvQuickSite/Start.cs
Expand Up @@ -26,6 +26,7 @@ namespace nvQuickSite
using System.IO;
using System.Linq;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Windows.Forms;

using Ionic.Zip;
Expand All @@ -52,6 +53,7 @@ public partial class Start : MetroUserControl
private long total;
private long lastVal;
private long sum;
private List<X509Certificate2> certificates;

/// <summary>
/// Initializes a new instance of the <see cref="Start"/> class.
Expand Down Expand Up @@ -128,6 +130,12 @@ private void ReadUserSettings()
this.txtSiteNameSuffix.Text = Properties.Settings.Default.SiteNameSuffixRecent;
this.chkSiteSpecificAppPool.Checked = Properties.Settings.Default.AppPoolRecent;
this.chkDeleteSiteIfExists.Checked = Properties.Settings.Default.DeleteSiteInIISRecent;
this.chkEnableSsl.Checked = Properties.Settings.Default.EnableSsl;
if (Properties.Settings.Default.CertificateFriendlyName != string.Empty)
{
this.cboCertificates.SelectedItem = Properties.Settings.Default.CertificateFriendlyName;
}

this.txtInstallBaseFolder.Text = Properties.Settings.Default.InstallBaseFolderRecent;

this.txtDBServerName.Text = Properties.Settings.Default.DatabaseServerNameRecent;
Expand All @@ -144,6 +152,12 @@ private void SaveUserSettings()
Properties.Settings.Default.SiteNameSuffixRecent = this.txtSiteNameSuffix.Text;
Properties.Settings.Default.AppPoolRecent = this.chkSiteSpecificAppPool.Checked;
Properties.Settings.Default.DeleteSiteInIISRecent = this.chkDeleteSiteIfExists.Checked;
Properties.Settings.Default.EnableSsl = this.chkEnableSsl.Checked;
if (this.cboCertificates.SelectedItem != null)
{
Properties.Settings.Default.CertificateFriendlyName = this.cboCertificates.SelectedItem.ToString();
}

Properties.Settings.Default.InstallBaseFolderRecent = this.txtInstallBaseFolder.Text;

Properties.Settings.Default.DatabaseServerNameRecent = this.txtDBServerName.Text;
Expand Down Expand Up @@ -412,6 +426,31 @@ private void txtSiteNamePrefix_TextChanged(object sender, EventArgs e)
this.txtDBName.Text = this.txtSiteNamePrefix.Text;
}

private void chkEnableSsl_CheckedChanged(object sender, EventArgs e)
{
this.cboCertificates.Visible = false;
if (this.chkEnableSsl.Checked)
{
this.LoadSslCertificates();
this.cboCertificates.Visible = true;
}
}

private void LoadSslCertificates()
{
this.cboCertificates.Items.Clear();
this.certificates = IISController.GetSslCertificates();
this.certificates.ForEach(c => this.cboCertificates.Items.Add(c.FriendlyName != string.Empty ? c.FriendlyName : c.Subject.Split(',')[0].Split('=')[1]));
if (this.cboCertificates.Items.Count > 0)
{
this.cboCertificates.SelectedIndex = 0;
if (Properties.Settings.Default.CertificateFriendlyName != string.Empty)
{
this.cboCertificates.SelectedItem = Properties.Settings.Default.CertificateFriendlyName;
}
}
}

private void btnSiteInfoNext_Click(object sender, EventArgs e)
{
bool proceed;
Expand Down Expand Up @@ -549,7 +588,8 @@ private void btnDatabaseInfoNext_Click(object sender, EventArgs e)
this.SiteName,
this.InstallFolder,
this.chkSiteSpecificAppPool.Checked,
this.chkDeleteSiteIfExists.Checked);
this.chkDeleteSiteIfExists.Checked,
this.certificates[this.cboCertificates.SelectedIndex]);

FileSystemController.UpdateHostsFile(this.SiteName);

Expand Down Expand Up @@ -668,7 +708,8 @@ private void myZip_ExtractProgress(object sender, ExtractProgressEventArgs e)

private void btnVisitSite_Click(object sender, EventArgs e)
{
var url = "http://" + this.SiteName;
var protocol = this.chkEnableSsl.Checked ? "https://" : "http://";
var url = protocol + this.SiteName;
Log.Logger.Information("Visiting {url}", url);
Process.Start(url);
Log.Logger.Information("Closing application");
Expand Down
8 changes: 7 additions & 1 deletion nvQuickSite/app.config
Expand Up @@ -52,14 +52,20 @@
<setting name="EnableLocalPackageInstall" serializeAs="String">
<value>False</value>
</setting>
<setting name="EnableSsl" serializeAs="String">
<value>False</value>
</setting>
<setting name="CertificateFriendlyName" serializeAs="String">
<value />
</setting>
</nvQuickSite.Properties.Settings>
</userSettings>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /></startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-8.0.0.0" newVersion="8.0.0.0" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
Expand Down
2 changes: 1 addition & 1 deletion nvQuickSite/data/latestVersion.json
@@ -1,3 +1,3 @@
{
"latestVersion": "2.2.0"
"latestVersion": "2.3.0"
}
4 changes: 2 additions & 2 deletions nvQuickSite/nvQuickSite.csproj
Expand Up @@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{3D661BAD-45EB-4524-9650-78805CD31682}</ProjectGuid>
Expand Down Expand Up @@ -279,7 +279,7 @@
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="Newtonsoft.Json">
<Version>13.0.1</Version>
<Version>13.0.2</Version>
</PackageReference>
<PackageReference Include="Octokit">
<Version>0.32.0</Version>
Expand Down