В рабочем проекте на ASP.NET MVC понадобилось дать пользователям сайта возможность самим добавлять доменные имена для существующего сайта.

Для управления IIS 7+ существует библиотека Microsoft.Web.Administration. Добавляем её в проект через NuGet

Install-Package Microsoft.Web.Administration

HTTP-привязка

  • создаём инстанс ServerManager
  • находим сайт
  • добавляем домен
  • не забываем сохранить изменения.

Формат записи домена - IP:Port:Hostname

Упрощенно выглядит так

using (var iisManager = new ServerManager())
{
    var site = iisManager.Sites["SiteName"];

    site.Bindings.Add(string.Format("*:{0}:{1}", 80, "user1.localtest.me"), "http");

    iisManager.CommitChanges();
}

C HTTPS слегка сложнее, потому что нужен сертификат. Теоретически, можно генерировать CSR, отдавать его пользователю и получать от него CRT. Но на мой взгляд это слишком эпично, поэтому от пользователя будем требовать PKCS12 (PFX)

  • открываем сертификат
  • добавляем в хранилище
  • добавляем домен, так же как и для HTTP, но еще передаём хэш сертификата и имя хранилища
  • говорим IIS, чтобы он требовал указания имени хоста для HTTPS запросов, иначе невозможно использовать несколько сертификатов для одного IP
using (var iisManager = new ServerManager())
{
    //...
    var certificate = new X509Certificate2("path/to/certificate.pfx", "certificate_password", 
        X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.MachineKeySet);

    var store = new X509Store(StoreName.My, StoreLocation.LocalMachine);
    store.Open(OpenFlags.OpenExistingOnly | OpenFlags.ReadWrite);
    store.Add(certificate);
    store.Close();

    var hash = certificate.GetCertHash();
    var storeName = store.Name;
    var bindingData = string.Format("*:{0}:{1}", 443, "user1.localtest.me");

    var binding = site.Bindings.Add(bindingData, hash, storeName);
    binding.Protocol = "https";
    binding.SetAttributeValue("sslFlags", 1);
    //...
}

Для успешной работы нужно, чтобы у текущего процесса были административные права.