Monday 19 November 2012

Dev tool to configure One to One Client Certificate Mappings in IIS 7.5

In my last post, I described a rather tedious and error prone method for configuring One To One client certificate mappings in IIS 7.5, so with a little bit of help I created a small WPF application that should ensure the smooth configuration of one to one client certificate mappings.

There is no validation as this is simply a developer tool and I'm too lazy to add it, you can have a look at this post for an example of textbox validation in WPF.

Xaml
<Window x:Class="IISCERTTOOL.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

        Title="MainWindow" Height="302" Width="477">

    <Grid>
        <Button Content="Add One to One Certificate Mapping" Height="23" HorizontalAlignment="Left" Margin="242,212,0,0" Name="Add" VerticalAlignment="Top" Width="191" Click="Add_Click" />
        <Label Content="UserName" Height="28" HorizontalAlignment="Left" Margin="46,50,0,0" Name="label1" VerticalAlignment="Top" Width="81" />
        <TextBox Height="23" HorizontalAlignment="Left" Margin="163,50,0,0" Name="UserName" VerticalAlignment="Top" Width="241" />
        <Label Content="Password" Height="28" HorizontalAlignment="Left" Margin="46,84,0,0" Name="label2" VerticalAlignment="Top" Width="81" />
        <PasswordBox Height="23" HorizontalAlignment="Left" Margin="163,89,0,0" Name="Password" VerticalAlignment="Top" Width="241" />
        <Label Content="Certificate" Height="28" HorizontalAlignment="Left" Margin="46,118,0,0" Name="label3" VerticalAlignment="Top" Width="81" />
        <TextBox Height="23" HorizontalAlignment="Left" Margin="163,123,0,0" Name="Certificate" VerticalAlignment="Top" Width="241" />
        <Label Content="WebSite" Height="28" HorizontalAlignment="Left" Margin="46,152,0,0" Name="label4" VerticalAlignment="Top" Width="81" />
        <ComboBox Height="23" HorizontalAlignment="Left" Margin="163,152,0,0" Name="WebSite" VerticalAlignment="Top" Width="241" />
        <Button Content="..." Height="20" HorizontalAlignment="Left" Margin="416,123,0,0" Name="SelectCertificate" VerticalAlignment="Top" Width="17" FontStyle="Normal" Click="SelectCertificate_Click" />
    </Grid>
</Window>

Code behind.
 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Data;
 using System.Windows.Documents;
 using System.Windows.Input;
 using System.Windows.Media;
 using System.Windows.Media.Imaging;
 using System.Windows.Navigation;
 using System.Windows.Shapes;
 using Microsoft.Web.Administration;
 using System.IO;
 using System.Diagnostics;
 
 
 namespace IISCERTTOOL
 {
     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
     public partial class MainWindow : Window
     {
         public MainWindow()
         {
             InitializeComponent();
 
             LoadWebSites();
         }
 
         private void SelectCertificate_Click(object sender, RoutedEventArgs e)
         {
             try
             {
                 Microsoft.Win32.OpenFileDialog dialog = new Microsoft.Win32.OpenFileDialog();
 
                 dialog.AddExtension = true;
                 dialog.CheckFileExists = true;
                 dialog.Filter = "cer files (*.cer)|*.cer";
                 dialog.Multiselect = false;
 
                 if ((bool)dialog.ShowDialog())
                 {
                     Certificate.Text = dialog.FileName;
                 }
             }
             catch (Exception ex)
             {
                 DisplayException(ex);
             }
 
         }
 
         private void Add_Click(object sender, RoutedEventArgs e)
         {
             try
             {
                 string publicKey = ReadKey(Certificate.Text.Trim());
 
                 if (!string.IsNullOrEmpty(publicKey) && ConfigureOneToOneCertMapping(UserName.Text.Trim(), Password.Password.Trim(), publicKey, WebSite.SelectedValue.ToString()))
                 {
                     MessageBox.Show("One to One Mapping successfully added");
                 }
                 else
                 {
                     MessageBox.Show("One to One Mapping was not added");
                 }
             }
             catch (Exception ex)
             {
                 DisplayException(ex);
             }
         }
         /// <summary>
         /// Read certificate file into a string
         /// </summary>
         private string ReadKey(string path)
         {
             StringBuilder publicKey = new StringBuilder();
 
             try
             {
                 string[] file = File.ReadAllLines(path).Skip(1).ToArray();
 
                 for (int i = 0; i < file.Length - 1; i++)
                 {
                     publicKey.Append(file[i]);
                 }
             }
             catch (Exception ex)
             {
                 DisplayException(ex);
             }
 
             return publicKey.ToString();
         }
 
         /// <summary>
         /// Grab all Websites on the server and populate the dropdown combobox.
         /// </summary>
         private void LoadWebSites()
         {
             try
             {
                 List<string> sites = new List<string>();
 
                 using (ServerManager serverManager = new ServerManager())
                 {
                     foreach (Site s in serverManager.Sites)
                     {
                         sites.Add(s.Name);
                     }
                 }
 
                 WebSite.ItemsSource = sites;
             }
             catch (Exception ex)
             {
                 DisplayException(ex);
             }
 
         }
 
         /// <summary>
         /// Configure OneToOne Certificate Mapping for client authenticated SSL/TLS
         /// </summary>
         private bool ConfigureOneToOneCertMapping(string UserName, string Password, string PublicKey, string WebSiteName)
         {
             bool result = false;
 
             using (ServerManager serverManager = new ServerManager())
             {
                 try
                 {
                     Configuration config = serverManager.GetApplicationHostConfiguration();
 
                     ConfigurationSection iisClientCertificateMappingAuthenticationSection = config.GetSection("system.webServer/security/authentication/iisClientCertificateMappingAuthentication", WebSiteName);
                     iisClientCertificateMappingAuthenticationSection["enabled"] = true;
                     iisClientCertificateMappingAuthenticationSection["oneToOneCertificateMappingsEnabled"] = true;
 
                     ConfigurationElementCollection oneToOneMappingsCollection = iisClientCertificateMappingAuthenticationSection.GetCollection("oneToOneMappings");
                     ConfigurationElement addElement = oneToOneMappingsCollection.CreateElement("add");
                     addElement["enabled"] = true;
                     addElement["userName"] = UserName;
                     addElement["password"] = Password;
                     addElement["certificate"] = PublicKey;
                     oneToOneMappingsCollection.Add(addElement);
 
                     ConfigurationSection accessSection = config.GetSection("system.webServer/security/access", WebSiteName);
                     accessSection["sslFlags"] = @"Ssl, SslNegotiateCert";
 
                     serverManager.CommitChanges();
 
                     result = true;
                 }
                 catch (Exception ex)
                 {
                     DisplayException(ex);
                 }
 
                 return result;
 
             }
 
         }
 
         /// <summary>
         /// Gets details of exception and displays them in a textbox.
         /// </summary>
         private static void DisplayException(Exception ex)
         {
             StringBuilder sb = new StringBuilder();
 
             StackTrace trace = new StackTrace();
 
             sb.AppendLine("Exception Occurred.");
 
             sb.AppendLine(string.Format("{0}.{1}",
                 trace.GetFrame(1).GetMethod().ReflectedType.Name, trace.GetFrame(1).GetMethod().Name));
 
 
             sb.AppendLine(string.Format("Source: {0}.", ex.Source));
             sb.AppendLine(string.Format("Type: {0}.", ex.GetType()));
             sb.AppendLine(string.Format("Message: {0}.", ex.Message));
 
             if (ex.InnerException != null)
             {
                 sb.AppendLine(string.Format("Inner Exception: {0}.", ex.InnerException.Message));
             }
 
             MessageBox.Show(sb.ToString());
         }
     }
 }

No comments:

Post a Comment