2014-11-05
Программное добавление HTTPS-привязки к сайту IIS
В рабочем проекте на 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);
//...
}
Для успешной работы нужно, чтобы у текущего процесса были административные права.