public async Task TestRequestAndInstallDnsCertificate() { var config = new AppSettingsAuthConfig(); var client = ArmHelper.GetWebSiteManagementClient(config); var kuduClient = KuduHelper.GetKuduClient(client, config); var body = new DnsAzureInstallModel() { AzureWebAppEnvironment = new AzureWebAppEnvironment(config.Tenant, config.SubscriptionId, config.ClientId, config.ClientSecret, config.ResourceGroupName, config.WebAppName), AcmeConfig = new AcmeConfig() { Host = "letsencrypt.ai4bots.com", PFXPassword = "******", RegistrationEmail = "*****@*****.**", RSAKeyLength = 2048 }, RelativeRecordSetName = "letsencrypt", ZoneName = "ai4bots.com", ResourceGroupName = "dns", SubscriptionId = new Guid("14fe4c66-c75a-4323-881b-ea53c1d86a9d"), CertificateSettings = new CertificateServiceSettings() }; var res = await kuduClient.HttpClient.PostAsync( "https://webappcfmv5fy7lcq7o.scm.azurewebsites.net/letsencrypt/api/certificates/challengeprovider/dns/azure/certificateinstall/azurewebapp?api-version=2017-09-01", new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json")); await ValidateResponse(body.AcmeConfig, res); }
public static async Task <IReadOnlyList <string> > GetLetsEncryptHostNames(IAzureWebAppEnvironment webAppEnvironment, bool staging) { Site site; using (var client = await ArmHelper.GetWebSiteManagementClient(webAppEnvironment)) { Trace.TraceInformation( "Getting Web App '{0}' (slot '{1}') from resource group '{2}'", webAppEnvironment.WebAppName, webAppEnvironment.SiteSlotName, webAppEnvironment.ResourceGroupName); site = client.WebApps.GetSiteOrSlot(webAppEnvironment.ResourceGroupName, webAppEnvironment.WebAppName, webAppEnvironment.SiteSlotName); } using (var httpClient = await ArmHelper.GetHttpClient(webAppEnvironment)) { var certRequestUri = $"/subscriptions/{webAppEnvironment.SubscriptionId}/providers/Microsoft.Web/certificates?api-version=2016-03-01"; Trace.TraceInformation("GET {0}", certRequestUri); var response = await ArmHelper.ExponentialBackoff().ExecuteAsync(async() => await httpClient.GetAsync(certRequestUri)); Trace.TraceInformation("Reading ARM certificate query response"); var body = await response.EnsureSuccessStatusCode().Content.ReadAsStringAsync(); var letsEncryptCerts = ExtractCertificates(body).Where(s => s.Issuer.Contains(staging ? "Fake LE" : "Let's Encrypt")); var leCertThumbprints = new HashSet <string>(letsEncryptCerts.Select(c => c.Thumbprint)); return(site.HostNameSslStates.Where(ssl => leCertThumbprints.Contains(ssl.Thumbprint)).Select(ssl => ssl.Name).ToArray()); } }
private async Task EnsureVirtualDirectorySetup() { if (virtualDirectorySetup) { Trace.TraceInformation("/.well-known already configured, skipping"); return; } using (var client = await ArmHelper.GetWebSiteManagementClient(this.azureEnvironment)) { var siteConfig = client.WebApps.GetSiteConfigurationOrSlot(azureEnvironment.ResourceGroupName, azureEnvironment.WebAppName, azureEnvironment.SiteSlotName); if (!IsVirtualDirectorySetup(siteConfig)) { var app = siteConfig.VirtualApplications.First(); if (app.VirtualDirectories == null) { app.VirtualDirectories = new List <VirtualDirectory>(); } app.VirtualDirectories.Add(new VirtualDirectory() { PhysicalPath = wellKnownPhysicalPath, VirtualPath = "/.well-known", }); client.WebApps.UpdateSiteConfigurationOrSlot(azureEnvironment.ResourceGroupName, azureEnvironment.WebAppName, azureEnvironment.SiteSlotName, siteConfig); } virtualDirectorySetup = true; } }
public ActionResult Index(AuthenticationModel model) { if (ModelState.IsValid) { try { using (var client = ArmHelper.GetWebSiteManagementClient(model)) { //Update web config. var site = client.Sites.GetSite(model.ResourceGroupName, model.WebAppName); var webappsettings = client.Sites.ListSiteAppSettings(model.ResourceGroupName, model.WebAppName); if (model.UpdateAppSettings) { var newAppSettingsValues = new Dictionary <string, string> { { AppSettingsAuthConfig.clientIdKey, model.ClientId.ToString() }, { AppSettingsAuthConfig.clientSecretKey, model.ClientSecret.ToString() }, { AppSettingsAuthConfig.subscriptionIdKey, model.SubscriptionId.ToString() }, { AppSettingsAuthConfig.tenantKey, model.Tenant }, { AppSettingsAuthConfig.resourceGroupNameKey, model.ResourceGroupName }, { AppSettingsAuthConfig.servicePlanResourceGroupNameKey, model.ServicePlanResourceGroupName } }; foreach (var appsetting in newAppSettingsValues) { if (!webappsettings.Properties.ContainsKey(appsetting.Key)) { webappsettings.Properties.Add(appsetting.Key, appsetting.Value); } else { webappsettings.Properties[appsetting.Key] = appsetting.Value; } } client.Sites.UpdateSiteAppSettings(model.ResourceGroupName, model.WebAppName, webappsettings); } else { var appSetting = new AppSettingsAuthConfig(); if (!ValidateModelVsAppSettings("ClientId", model.ClientId.ToString(), appSetting.ClientId.ToString()) || !ValidateModelVsAppSettings("ClientSecret", appSetting.ClientSecret, model.ClientSecret) || !ValidateModelVsAppSettings("ResourceGroupName", appSetting.ResourceGroupName, model.ResourceGroupName) || !ValidateModelVsAppSettings("SubScriptionId", appSetting.SubscriptionId.ToString(), model.SubscriptionId.ToString()) || !ValidateModelVsAppSettings("Tenant", appSetting.Tenant, model.Tenant) || !ValidateModelVsAppSettings("ServicePlanResourceGroupName", appSetting.ServicePlanResourceGroupName, model.ServicePlanResourceGroupName)) { model.ErrorMessage = "One or more app settings are different from the values entered, do you want to update the app settings?"; return(View(model)); } } } return(RedirectToAction("Hostname")); } catch (Exception ex) { Trace.TraceError(ex.ToString()); model.ErrorMessage = ex.ToString(); } } return(View(model)); }
public ActionResult Hostname(string id) { var settings = new AppSettingsAuthConfig(); var model = new HostnameModel(); List <ValidationResult> validationResult = null; if (settings.IsValid(out validationResult)) { var client = ArmHelper.GetWebSiteManagementClient(settings); var site = client.Sites.GetSiteOrSlot(settings.ResourceGroupName, settings.WebAppName, settings.SiteSlotName); model.HostNames = site.HostNames; model.HostNameSslStates = site.HostNameSslStates; model.Certificates = client.Certificates.GetCertificates(settings.ServicePlanResourceGroupName).Value; model.InstalledCertificateThumbprint = id; if (model.HostNames.Count == 1) { model.ErrorMessage = "No custom host names registered. At least one custom domain name must be registed for the web site to request a letsencrypt certificate."; } } else { var errorMessage = string.Join(" ,", validationResult.Select(s => s.ErrorMessage)); model.ErrorMessage = $"Application settings was invalid, please wait a little and try to reload page if you just updated appsettings. Validation errors: {errorMessage}"; } return(View(model)); }
public async Task TestRequestDnsCertificate() { var config = new AppSettingsAuthConfig(); var client = await ArmHelper.GetWebSiteManagementClient(config); var kuduClient = KuduHelper.GetKuduClient(client, config); var body = new DnsAzureModel() { AzureDnsEnvironment = new AzureDnsEnvironment(config.Tenant, new Guid("14fe4c66-c75a-4323-881b-ea53c1d86a9d"), config.ClientId, config.ClientSecret, "dns", "ai4bots.com", "@"), AcmeConfig = new AcmeConfig() { Host = "ai4bots.com", PFXPassword = "******", RegistrationEmail = "*****@*****.**", RSAKeyLength = 2048 } }; var res = await kuduClient.HttpClient.PostAsync( "https://webappcfmv5fy7lcq7o.scm.azurewebsites.net/letsencrypt/api/certificates/challengeprovider/dns/azure?api-version=2017-09-01", new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json")); await ValidateResponse(body.AcmeConfig, res); }
public async Task TestRequestAndInstallCertificate() { var config = new AppSettingsAuthConfig(); var client = ArmHelper.GetWebSiteManagementClient(config); var kuduClient = KuduHelper.GetKuduClient(client, config); var body = new HttpKuduInstallModel() { AzureEnvironment = new AzureWebAppEnvironment(config.Tenant, config.SubscriptionId, config.ClientId, config.ClientSecret, config.ResourceGroupName, config.WebAppName), AcmeConfig = new AcmeConfig() { Host = "letsencrypt.sjkp.dk", PFXPassword = "******", RegistrationEmail = "*****@*****.**", RSAKeyLength = 2048 }, AuthorizationChallengeProviderConfig = new AuthorizationChallengeProviderConfig(), CertificateSettings = new CertificateServiceSettings() }; var res = await kuduClient.HttpClient.PostAsync( "https://webappcfmv5fy7lcq7o.scm.azurewebsites.net/letsencrypt/api/certificates/challengeprovider/http/kudu/certificateinstall/azurewebapp?api-version=2017-09-01", new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json")); await ValidateResponse(body.AcmeConfig, res); }
public KuduFileSystemAuthorizationChallengeProvider(IAzureWebAppEnvironment azureEnvironment, IAuthorizationChallengeProviderConfig config) { this.config = config; var website = ArmHelper.GetWebSiteManagementClient(azureEnvironment); this.kuduClient = KuduHelper.GetKuduClient(website, azureEnvironment); }
public void Install(ICertificateInstallModel model) { var cert = model.CertificateInfo; using (var webSiteClient = ArmHelper.GetWebSiteManagementClient(azureEnvironment)) { var s = webSiteClient.WebApps.GetSiteOrSlot(azureEnvironment.ResourceGroupName, azureEnvironment.WebAppName, azureEnvironment.SiteSlotName); Trace.TraceInformation(String.Format("Installing certificate {0} on azure with server farm id {1}", cert.Name, s.ServerFarmId)); var newCert = new Certificate() { PfxBlob = cert.PfxCertificate, Password = cert.Password, Location = s.Location, ServerFarmId = s.ServerFarmId, Name = model.Host + "-" + cert.Certificate.Thumbprint }; //BUG https://github.com/sjkp/letsencrypt-siteextension/issues/99 //using this will not install the certificate with the correct webSpace property set, //and the app service will be unable to find the certificate if the app service plan has been moved between resource groups. //webSiteClient.Certificates.CreateOrUpdate(azureEnvironment.ServicePlanResourceGroupName, cert.Certificate.Subject.Replace("CN=", ""), newCert); var client = ArmHelper.GetHttpClient(azureEnvironment); var body = JsonConvert.SerializeObject(newCert, JsonHelper.DefaultSerializationSettings); var t = client.PutAsync($"/subscriptions/{azureEnvironment.SubscriptionId}/resourceGroups/{azureEnvironment.ServicePlanResourceGroupName}/providers/Microsoft.Web/certificates/{newCert.Name}?api-version=2016-03-01", new StringContent(body, Encoding.UTF8, "application/json")).Result; t.EnsureSuccessStatusCode(); foreach (var dnsName in model.AllDnsIdentifiers) { var sslState = s.HostNameSslStates.FirstOrDefault(g => g.Name == dnsName); if (sslState == null) { sslState = new HostNameSslState() { Name = model.Host, SslState = settings.UseIPBasedSSL ? SslState.IpBasedEnabled : SslState.SniEnabled, }; s.HostNameSslStates.Add(sslState); } else { //First time setting the HostNameSslState it is set to disabled. sslState.SslState = settings.UseIPBasedSSL ? SslState.IpBasedEnabled : SslState.SniEnabled; } sslState.ToUpdate = true; sslState.Thumbprint = cert.Certificate.Thumbprint; } webSiteClient.WebApps.BeginCreateOrUpdateSiteOrSlot(azureEnvironment.ResourceGroupName, azureEnvironment.WebAppName, azureEnvironment.SiteSlotName, s); } }
public async Task <bool> IsVirtualDirectorySetup() { using (var client = await ArmHelper.GetWebSiteManagementClient(this.azureEnvironment)) { var siteConfig = client.WebApps.GetSiteConfigurationOrSlot(azureEnvironment.ResourceGroupName, azureEnvironment.WebAppName, azureEnvironment.SiteSlotName); return(IsVirtualDirectorySetup(siteConfig)); } }
/// <summary> /// Used for automatic installation of letsencrypt certificate /// </summary> public void AddCertificate() { Trace.TraceInformation("Staring add certificate"); using (var client = ArmHelper.GetWebSiteManagementClient(settings)) { Trace.TraceInformation($"Add certificate for acmeConfig hostname {string.Join(", ", acmeConfig.Hostnames)}"); if (acmeConfig.Hostnames.Any()) { RequestAndInstallInternal(this.acmeConfig); } } }
public async Task <List <AcmeConfig> > RenewCertificate(bool skipInstallCertificate = false, int renewXNumberOfDaysBeforeExpiration = 0) { Trace.TraceInformation("Checking certificate"); var ss = SettingsStore.Instance.Load(); using (var client = ArmHelper.GetWebSiteManagementClient(settings)) using (var httpClient = ArmHelper.GetHttpClient(settings)) { //Cant just get certificates by resource group, because sites that have been moved, have their certs sitting in the old RG. //Also cant use client.Certificates.List() due to bug in the nuget var response = await httpClient.GetAsync($"/subscriptions/{settings.SubscriptionId}/providers/Microsoft.Web/certificates?api-version=2016-03-01"); response.EnsureSuccessStatusCode(); var body = await response.Content.ReadAsStringAsync(); IEnumerable <Certificate> certs = JsonConvert.DeserializeObject <Certificate[]>(body, JsonHelper.DefaultSerializationSettings); var expiringCerts = certs.Where(s => s.ExpirationDate < DateTime.UtcNow.AddDays(renewXNumberOfDaysBeforeExpiration) && (s.Issuer.Contains("Let's Encrypt") || s.Issuer.Contains("Fake LE"))); if (expiringCerts.Count() == 0) { Trace.TraceInformation(string.Format("No certificates installed issued by Let's Encrypt that are about to expire within the next {0} days. Skipping.", renewXNumberOfDaysBeforeExpiration)); } var res = new List <AcmeConfig>(); foreach (var toExpireCert in expiringCerts) { Trace.TraceInformation("Starting renew of certificate " + toExpireCert.Name + " expiration date " + toExpireCert.ExpirationDate); var site = client.WebApps.Get(settings.ResourceGroupName, settings.WebAppName); var sslStates = site.HostNameSslStates.Where(s => s.Thumbprint == toExpireCert.Thumbprint); if (!sslStates.Any()) { Trace.TraceInformation(String.Format("Certificate {0} was not assigned any hostname, skipping update", toExpireCert.Thumbprint)); continue; } var target = new AcmeConfig() { RegistrationEmail = this.acmeConfig.RegistrationEmail ?? ss.FirstOrDefault(s => s.Name == "email").Value, Host = sslStates.First().Name, BaseUri = this.acmeConfig.BaseUri ?? ss.FirstOrDefault(s => s.Name == "baseUri").Value, AlternateNames = sslStates.Skip(1).Select(s => s.Name).ToList(), PFXPassword = this.acmeConfig.PFXPassword, RSAKeyLength = this.acmeConfig.RSAKeyLength }; if (!skipInstallCertificate) { await RequestAndInstallInternalAsync(target); } res.Add(target); } return(res); } }
public List <string> RemoveExpired(int removeXNumberOfDaysBeforeExpiration = 0) { using (var webSiteClient = ArmHelper.GetWebSiteManagementClient(azureEnvironment)) { var certs = webSiteClient.Certificates.ListByResourceGroup(azureEnvironment.ServicePlanResourceGroupName); var tobeRemoved = certs.Where(s => s.ExpirationDate < DateTime.UtcNow.AddDays(removeXNumberOfDaysBeforeExpiration) && (s.Issuer.Contains("Let's Encrypt") || s.Issuer.Contains("Fake LE"))).ToList(); tobeRemoved.ForEach(s => RemoveCertificate(webSiteClient, s)); return(tobeRemoved.Select(s => s.Thumbprint).ToList()); } }
public IEnumerable <Target> RenewCertificate(bool debug = false) { Trace.TraceInformation("Checking certificate"); var settings = new AppSettingsAuthConfig(); var ss = SettingsStore.Instance.Load(); using (var client = ArmHelper.GetWebSiteManagementClient(settings)) { var certs = client.Certificates.GetCertificates(settings.ServicePlanResourceGroupName).Value; var expiringCerts = certs.Where(s => s.ExpirationDate < DateTime.UtcNow.AddDays(settings.RenewXNumberOfDaysBeforeExpiration) && (s.Issuer.Contains("Let's Encrypt") || s.Issuer.Contains("Fake LE"))); if (expiringCerts.Count() == 0) { Trace.TraceInformation(string.Format("No certificates installed issued by Let's Encrypt that are about to expire within the next {0} days. Skipping.", settings.RenewXNumberOfDaysBeforeExpiration)); } foreach (var toExpireCert in expiringCerts) { Trace.TraceInformation("Starting renew of certificate " + toExpireCert.Name + " expiration date " + toExpireCert.ExpirationDate); var site = client.Sites.GetSite(settings.ResourceGroupName, settings.WebAppName); var sslStates = site.HostNameSslStates.Where(s => s.Thumbprint == toExpireCert.Thumbprint); if (!sslStates.Any()) { Trace.TraceInformation(String.Format("Certificate {0} was not assigned any hostname, skipping update", toExpireCert.Thumbprint)); continue; } var target = new Target() { WebAppName = settings.WebAppName, Tenant = settings.Tenant, SubscriptionId = settings.SubscriptionId, ClientId = settings.ClientId, ClientSecret = settings.ClientSecret, ResourceGroupName = settings.ResourceGroupName, Email = settings.Email ?? ss.FirstOrDefault(s => s.Name == "email").Value, Host = sslStates.First().Name, BaseUri = settings.BaseUri ?? ss.FirstOrDefault(s => s.Name == "baseUri").Value, ServicePlanResourceGroupName = settings.ServicePlanResourceGroupName, AlternativeNames = sslStates.Skip(1).Select(s => s.Name).ToList(), UseIPBasedSSL = settings.UseIPBasedSSL, SiteSlotName = settings.SiteSlotName }; if (!debug) { RequestAndInstallInternal(target); } yield return(target); } } }
private void SetViewBagHostnames() { var settings = new AppSettingsAuthConfig(); var client = ArmHelper.GetWebSiteManagementClient(settings); var site = client.Sites.GetSiteOrSlot(settings.ResourceGroupName, settings.WebAppName, settings.SiteSlotName); var model = new HostnameModel(); ViewBag.HostNames = site.HostNames.Where(s => !s.EndsWith(settings.AzureWebSitesDefaultDomainName)).Select(s => new SelectListItem() { Text = s, Value = s }); }
public async Task <List <string> > RemoveExpired(int removeXNumberOfDaysBeforeExpiration = 0) { using (var webSiteClient = await ArmHelper.GetWebSiteManagementClient(azureEnvironment)) { var certs = webSiteClient.Certificates.ListByResourceGroup(azureEnvironment.ServicePlanResourceGroupName); var site = webSiteClient.WebApps.GetSiteOrSlot(azureEnvironment.ResourceGroupName, azureEnvironment.WebAppName, azureEnvironment.SiteSlotName); var tobeRemoved = certs.Where(s => s.ExpirationDate < DateTime.UtcNow.AddDays(removeXNumberOfDaysBeforeExpiration) && (s.Issuer.Contains("Let's Encrypt") || s.Issuer.Contains("Fake LE")) && !site.HostNameSslStates.Any(hostNameBindings => hostNameBindings.Thumbprint == s.Thumbprint)).ToList(); foreach (var cert in tobeRemoved) { await RemoveCertificate(webSiteClient, cert); } return(tobeRemoved.Select(s => s.Thumbprint).ToList()); } }
public async Task TestRenewCertificate() { var config = new AppSettingsAuthConfig(); var client = ArmHelper.GetWebSiteManagementClient(config); var kuduClient = KuduHelper.GetKuduClient(client, config); var res = await kuduClient.HttpClient.PostAsync("https://webappcfmv5fy7lcq7o-vnext.scm.azurewebsites.net/letsencrypt/api/certificates/renew?api-version=2017-09-01", new StringContent("")); Assert.AreEqual(System.Net.HttpStatusCode.OK, res.StatusCode); var model = JsonConvert.DeserializeObject <CertificateInstallModel[]>(await res.Content.ReadAsStringAsync()); Assert.AreEqual(1, model.Count()); File.WriteAllBytes(Path.GetFileName(model.First().CertificateInfo.Name), model.First().CertificateInfo.PfxCertificate); }
/// <summary> /// Used for automatic installation of hostnames bindings and certificate /// upon first installation on the site extension and if hostnames are specified in app settings /// </summary> public void SetupHostnameAndCertificate() { Trace.TraceInformation("Setup hostname and certificates"); var settings = new AppSettingsAuthConfig(); using (var client = ArmHelper.GetWebSiteManagementClient(settings)) { var s = client.Sites.GetSite(settings.ResourceGroupName, settings.WebAppName); foreach (var hostname in settings.Hostnames) { if (s.HostNames.Any(existingHostname => string.Equals(existingHostname, hostname, StringComparison.InvariantCultureIgnoreCase))) { Trace.TraceInformation("Hostname already configured skipping installation"); continue; } Trace.TraceInformation("Setting up hostname and lets encrypt certificate for " + hostname); client.Sites.CreateOrUpdateSiteOrSlotHostNameBinding(settings.ResourceGroupName, settings.WebAppName, settings.SiteSlotName, hostname, new HostNameBinding() { CustomHostNameDnsRecordType = CustomHostNameDnsRecordType.CName, HostNameType = HostNameType.Verified, SiteName = settings.WebAppName, Location = s.Location }); } if (settings.Hostnames.Any()) { RequestAndInstallInternal(new Target() { BaseUri = settings.BaseUri, ClientId = settings.ClientId, ClientSecret = settings.ClientSecret, Email = settings.Email, Host = settings.Hostnames.First(), ResourceGroupName = settings.ResourceGroupName, SubscriptionId = settings.SubscriptionId, Tenant = settings.Tenant, WebAppName = settings.WebAppName, ServicePlanResourceGroupName = settings.ServicePlanResourceGroupName, AlternativeNames = settings.Hostnames.Skip(1).ToList(), SiteSlotName = settings.SiteSlotName, UseIPBasedSSL = settings.UseIPBasedSSL }); } } }
public ActionResult Hostname(string id) { var settings = new AppSettingsAuthConfig(); var client = ArmHelper.GetWebSiteManagementClient(settings); var site = client.Sites.GetSite(settings.ResourceGroupName, settings.WebAppName); var model = new HostnameModel(); model.HostNames = site.HostNames; model.HostNameSslStates = site.HostNameSslStates; model.Certificates = client.Certificates.GetCertificates(settings.ServicePlanResourceGroupName).Value; model.InstalledCertificateThumbprint = id; if (model.HostNames.Count == 1) { model.ErrorMessage = "No custom host names registered. At least one custom domain name must be registed for the web site to request a letsencrypt certificate."; } return(View(model)); }
public async Task <ActionResult> AddHostname() { var settings = new AppSettingsAuthConfig(); using (var client = await ArmHelper.GetWebSiteManagementClient(settings)) { var s = client.WebApps.GetSiteOrSlot(settings.ResourceGroupName, settings.WebAppName, settings.SiteSlotName); foreach (var hostname in settings.Hostnames) { client.WebApps.CreateOrUpdateSiteOrSlotHostNameBinding(settings.ResourceGroupName, settings.WebAppName, settings.SiteSlotName, hostname, new HostNameBinding { CustomHostNameDnsRecordType = CustomHostNameDnsRecordType.CName, HostNameType = HostNameType.Verified, SiteName = settings.WebAppName, }); } } return(View()); }
public ActionResult AddHostname() { var settings = new AppSettingsAuthConfig(); using (var client = ArmHelper.GetWebSiteManagementClient(settings)) { var s = client.Sites.GetSite(settings.ResourceGroupName, settings.WebAppName); foreach (var hostname in settings.Hostnames) { client.Sites.CreateOrUpdateSiteHostNameBinding(settings.ResourceGroupName, settings.WebAppName, hostname, new Microsoft.Azure.Management.WebSites.Models.HostNameBinding() { CustomHostNameDnsRecordType = Microsoft.Azure.Management.WebSites.Models.CustomHostNameDnsRecordType.CName, HostNameType = Microsoft.Azure.Management.WebSites.Models.HostNameType.Verified, SiteName = settings.WebAppName, Location = s.Location }); } } return(View()); }
public async Task GetPublishingCredentials() { var model = new AppSettingsAuthConfig(); var helper = ArmHelper.GetWebSiteManagementClient(model); var kuduClient = KuduHelper.GetKuduClient(helper, model); //var res = await kuduClient.GetScmInfo(); var dir = await kuduClient.GetFile("site/wwwroot/host.json"); using (var ms = new MemoryStream()) { var sw = new StreamWriter(ms); sw.WriteLine("Hell asd asd asd "); sw.Flush(); await kuduClient.PutFile("site/wwwroot/.well-known/acme-challenge2/test.json", ms); } }
public static async Task<IReadOnlyList<string>> GetNonExpiringLetsEncryptHostNames(IAzureWebAppEnvironment webAppEnvironment, bool staging, int renewXNumberOfDaysBeforeExpiration) { Site site; using (var client = await ArmHelper.GetWebSiteManagementClient(webAppEnvironment).ConfigureAwait(false)) { var webAppName = webAppEnvironment.WebAppName; var resourceGroupName = webAppEnvironment.ResourceGroupName; var siteSlotName = webAppEnvironment.SiteSlotName; Trace.TraceInformation( "Getting Web App '{0}' (slot '{1}') from resource group '{2}'", webAppName, siteSlotName, resourceGroupName); site = client.WebApps.GetSiteOrSlot(resourceGroupName, webAppName, siteSlotName); if (site == null) { throw new InvalidOperationException( $"Could not find web app '{webAppName}' (slot '{siteSlotName}') under Resource Groups '{resourceGroupName}'"); } } using (var httpClient = await ArmHelper.GetHttpClient(webAppEnvironment).ConfigureAwait(false)) { var certRequestUri = $"/subscriptions/{webAppEnvironment.SubscriptionId}/providers/Microsoft.Web/certificates?api-version=2016-03-01"; Trace.TraceInformation("GET {0}", certRequestUri); var response = await ArmHelper.ExponentialBackoff().ExecuteAsync(() => httpClient.GetAsync(new Uri(certRequestUri, UriKind.Relative))).ConfigureAwait(false); Trace.TraceInformation("Reading ARM certificate query response"); var body = await response.EnsureSuccessStatusCode().Content.ReadAsStringAsync().ConfigureAwait(false); var letsEncryptIssuerNames = staging ? s_letsEncrypStagingtIssuerNames : s_letsEncryptIssuerNames; var letsEncryptNonExpiringCerts = ExtractCertificates(body).Where(cert => letsEncryptIssuerNames.Contains(cert.Issuer) && cert.ExpirationDate > DateTime.UtcNow.AddDays(renewXNumberOfDaysBeforeExpiration)); var letsEncryptNonExpiringThumbprints = new HashSet<string>(letsEncryptNonExpiringCerts.Select(c => c.Thumbprint)); return site.HostNameSslStates.Where(ssl => letsEncryptNonExpiringThumbprints.Contains(ssl.Thumbprint)).Select(ssl => ssl.Name).ToArray(); } }
public ActionResult Index(AuthenticationModel model) { if (ModelState.IsValid) { try { using (var client = ArmHelper.GetWebSiteManagementClient(model)) { //Update web config. var site = client.Sites.GetSiteOrSlot(model.ResourceGroupName, model.WebAppName, model.SiteSlotName); //Validate that the service plan resource group name is correct, to avoid more issues on this specific problem. var azureServerFarmResourceGroup = site.ServerFarmResourceGroup(); if (!string.Equals(azureServerFarmResourceGroup, model.ServicePlanResourceGroupName, StringComparison.InvariantCultureIgnoreCase)) { ModelState.AddModelError("ServicePlanResourceGroupName", string.Format("The Service Plan Resource Group registered on the Web App in Azure in the ServerFarmId property '{0}' does not match the value you entered here {1}", azureServerFarmResourceGroup, model.ServicePlanResourceGroupName)); return(View(model)); } var webappsettings = client.Sites.ListSiteOrSlotAppSettings(model.ResourceGroupName, model.WebAppName, model.SiteSlotName); if (model.UpdateAppSettings) { var newAppSettingsValues = new Dictionary <string, string> { { AppSettingsAuthConfig.clientIdKey, model.ClientId.ToString() }, { AppSettingsAuthConfig.clientSecretKey, model.ClientSecret.ToString() }, { AppSettingsAuthConfig.subscriptionIdKey, model.SubscriptionId.ToString() }, { AppSettingsAuthConfig.tenantKey, model.Tenant }, { AppSettingsAuthConfig.resourceGroupNameKey, model.ResourceGroupName }, { AppSettingsAuthConfig.siteSlotNameKey, model.SiteSlotName }, { AppSettingsAuthConfig.servicePlanResourceGroupNameKey, model.ServicePlanResourceGroupName }, { AppSettingsAuthConfig.useIPBasedSSL, model.UseIPBasedSSL.ToString().ToLowerInvariant() } }; foreach (var appsetting in newAppSettingsValues) { if (!webappsettings.Properties.ContainsKey(appsetting.Key)) { webappsettings.Properties.Add(appsetting.Key, appsetting.Value); } else { webappsettings.Properties[appsetting.Key] = appsetting.Value; } } client.Sites.UpdateSiteOrSlotAppSettings(model.ResourceGroupName, model.WebAppName, model.SiteSlotName, webappsettings); ConfigurationManager.RefreshSection("appSettings"); } else { var appSetting = new AppSettingsAuthConfig(); if (!ValidateModelVsAppSettings("ClientId", appSetting.ClientId.ToString(), model.ClientId.ToString()) || !ValidateModelVsAppSettings("ClientSecret", appSetting.ClientSecret, model.ClientSecret) || !ValidateModelVsAppSettings("ResourceGroupName", appSetting.ResourceGroupName, model.ResourceGroupName) || !ValidateModelVsAppSettings("SubScriptionId", appSetting.SubscriptionId.ToString(), model.SubscriptionId.ToString()) || !ValidateModelVsAppSettings("Tenant", appSetting.Tenant, model.Tenant) || !ValidateModelVsAppSettings("SiteSlotName", appSetting.SiteSlotName, model.SiteSlotName) || !ValidateModelVsAppSettings("ServicePlanResourceGroupName", appSetting.ServicePlanResourceGroupName, model.ServicePlanResourceGroupName) || !ValidateModelVsAppSettings("UseIPBasedSSL", appSetting.UseIPBasedSSL.ToString().ToLowerInvariant(), model.UseIPBasedSSL.ToString().ToLowerInvariant())) { model.ErrorMessage = "One or more app settings are different from the values entered, do you want to update the app settings?"; return(View(model)); } } } return(RedirectToAction("PleaseWait")); } catch (Exception ex) { Trace.TraceError(ex.ToString()); model.ErrorMessage = ex.ToString(); } } return(View(model)); }
public static string RequestAndInstallInternal(Target target) { BaseURI = target.BaseUri ?? "https://acme-staging.api.letsencrypt.org/"; configPath = ConfigPath(BaseURI); try { webSiteClient = ArmHelper.GetWebSiteManagementClient(target); } catch (Exception ex) { Trace.TraceError("Unabled to create Azure Web Site Management client " + ex.ToString()); throw; } if (!Directory.Exists(configPath)) { Directory.CreateDirectory(configPath); } var email = target.Email; try { using (var signer = new RS256Signer()) { signer.Init(); var signerPath = Path.Combine(configPath, "Signer"); if (File.Exists(signerPath)) { Trace.TraceInformation($"Loading Signer from {signerPath}"); using (var signerStream = File.OpenRead(signerPath)) signer.Load(signerStream); } using (client = new AcmeClient(new Uri(BaseURI), new AcmeServerDirectory(), signer)) { client.Init(); Trace.TraceInformation("\nGetting AcmeServerDirectory"); client.GetDirectory(true); var registrationPath = Path.Combine(configPath, "Registration"); if (File.Exists(registrationPath)) { Trace.TraceInformation($"Loading Registration from {registrationPath}"); using (var registrationStream = File.OpenRead(registrationPath)) client.Registration = AcmeRegistration.Load(registrationStream); } else { var contacts = new string[] { }; if (!String.IsNullOrEmpty(email)) { email = "mailto:" + email; contacts = new string[] { email }; } Trace.TraceInformation("Calling Register"); var registration = client.Register(contacts); Trace.TraceInformation("Updating Registration"); client.UpdateRegistration(true, true); Trace.TraceInformation("Saving Registration"); using (var registrationStream = File.OpenWrite(registrationPath)) client.Registration.Save(registrationStream); Trace.TraceInformation("Saving Signer"); using (var signerStream = File.OpenWrite(signerPath)) signer.Save(signerStream); } // if (Options.Renew) // { // CheckRenewals(); //#if DEBUG // Trace.TraceInformation("Press enter to continue."); // Trace.ReadLine(); //#endif // return; // } return(Auto(target)); } } } catch (Exception e) { var acmeWebException = e as AcmeClient.AcmeWebException; if (acmeWebException != null) { Trace.TraceError(acmeWebException.Message); Trace.TraceError("ACME Server Returned:"); Trace.TraceError(acmeWebException.Response.ContentAsString); } else { Trace.TraceError(e.ToString()); } throw; } }
private async Task <KuduRestClient> GetKuduRestClient() { var website = await ArmHelper.GetWebSiteManagementClient(azureEnvironment); return(KuduHelper.GetKuduClient(website, azureEnvironment)); }
public async Task <ActionResult> Index(AuthenticationModel model) { if (ModelState.IsValid) { try { using (var client = await ArmHelper.GetWebSiteManagementClient(model)) { //Update web config. var site = client.WebApps.GetSiteOrSlot(model.ResourceGroupName, model.WebAppName, model.SiteSlotName); if (site == null) { ModelState.AddModelError(nameof(model.ResourceGroupName), string.Format("No web app could be found, please validate that Resource Group Name and/or Site Slot Name are correct")); return(View(model)); } //Validate that the service plan resource group name is correct, to avoid more issues on this specific problem. var azureServerFarmResourceGroup = site.ServerFarmResourceGroup(); if (!string.Equals(azureServerFarmResourceGroup, model.ServicePlanResourceGroupName, StringComparison.InvariantCultureIgnoreCase)) { ModelState.AddModelError("ServicePlanResourceGroupName", string.Format("The Service Plan Resource Group registered on the Web App in Azure in the ServerFarmId property '{0}' does not match the value you entered here {1}", azureServerFarmResourceGroup, model.ServicePlanResourceGroupName)); return(View(model)); } var appServicePlan = client.AppServicePlans.Get(model.ServicePlanResourceGroupName, site.ServerFarmName()); if (appServicePlan.Sku.Tier.Equals("Free") || appServicePlan.Sku.Tier.Equals("Shared")) { ModelState.AddModelError("ServicePlanResourceGroupName", $"The Service Plan is using the {appServicePlan.Sku.Tier} which doesn't support SSL certificates"); return(View(model)); } var path = new PathProvider(model); if (model.RunFromPackage && !await path.IsVirtualDirectorySetup() && !model.UpdateAppSettings) { ModelState.AddModelError("UpdateAppSettings", string.Format("The site is using Run From Package. You need to to allow the site-extension to update app settings to setup the virtual directory.")); return(View(model)); } var webappsettings = client.WebApps.ListSiteOrSlotAppSettings(model.ResourceGroupName, model.WebAppName, model.SiteSlotName); if (model.UpdateAppSettings) { var newAppSettingsValues = new Dictionary <string, string> { { AppSettingsAuthConfig.clientIdKey, model.ClientId.ToString() }, { AppSettingsAuthConfig.clientSecretKey, model.ClientSecret.ToString() }, { AppSettingsAuthConfig.subscriptionIdKey, model.SubscriptionId.ToString() }, { AppSettingsAuthConfig.tenantKey, model.Tenant }, { AppSettingsAuthConfig.resourceGroupNameKey, model.ResourceGroupName }, { AppSettingsAuthConfig.siteSlotNameKey, model.SiteSlotName }, { AppSettingsAuthConfig.servicePlanResourceGroupNameKey, model.ServicePlanResourceGroupName }, { AppSettingsAuthConfig.useIPBasedSSL, model.UseIPBasedSSL.ToString().ToLowerInvariant() } }; foreach (var appsetting in newAppSettingsValues) { if (!webappsettings.Properties.ContainsKey(appsetting.Key)) { webappsettings.Properties.Add(appsetting.Key, appsetting.Value); } else { webappsettings.Properties[appsetting.Key] = appsetting.Value; } } client.WebApps.UpdateSiteOrSlotAppSettings(model.ResourceGroupName, model.WebAppName, model.SiteSlotName, webappsettings); ConfigurationManager.RefreshSection("appSettings"); await path.ChallengeDirectory(true); } else { var appSetting = new AppSettingsAuthConfig(); if (!ValidateModelVsAppSettings("ClientId", appSetting.ClientId.ToString(), model.ClientId.ToString()) || !ValidateModelVsAppSettings("ClientSecret", appSetting.ClientSecret, model.ClientSecret) || !ValidateModelVsAppSettings("ResourceGroupName", appSetting.ResourceGroupName, model.ResourceGroupName) || !ValidateModelVsAppSettings("SubScriptionId", appSetting.SubscriptionId.ToString(), model.SubscriptionId.ToString()) || !ValidateModelVsAppSettings("Tenant", appSetting.Tenant, model.Tenant) || !ValidateModelVsAppSettings("SiteSlotName", appSetting.SiteSlotName, model.SiteSlotName) || !ValidateModelVsAppSettings("ServicePlanResourceGroupName", appSetting.ServicePlanResourceGroupName, model.ServicePlanResourceGroupName) || !ValidateModelVsAppSettings("UseIPBasedSSL", appSetting.UseIPBasedSSL.ToString().ToLowerInvariant(), model.UseIPBasedSSL.ToString().ToLowerInvariant())) { model.ErrorMessage = "One or more app settings are different from the values entered, do you want to update the app settings?"; return(View(model)); } } } return(RedirectToAction("PleaseWait")); } catch (Exception ex) { Trace.TraceError(ex.ToString()); model.ErrorMessage = ex.ToString(); } } return(View(model)); }
private async Task <int> RenewCore(RenewalParameters renewalParams) { Trace.TraceInformation("Generating SSL certificate with parameters: {0}", renewalParams); Trace.TraceInformation("Generating secure PFX password for '{0}'...", renewalParams.WebApp); var pfxPassData = new byte[32]; s_randomGenerator.GetBytes(pfxPassData); Trace.TraceInformation( "Adding SSL cert for '{0}{1}'...", renewalParams.WebApp, renewalParams.GroupName == null ? String.Empty : $"[{renewalParams.GroupName}]"); azureEnvironment = new AzureWebAppEnvironment( renewalParams.TenantId, renewalParams.SubscriptionId, renewalParams.ClientId, renewalParams.ClientSecret, renewalParams.ResourceGroup, renewalParams.WebApp, renewalParams.ServicePlanResourceGroup, renewalParams.SiteSlotName) { WebRootPath = renewalParams.WebRootPath, AzureWebSitesDefaultDomainName = renewalParams.AzureDefaultWebsiteDomainName ?? DefaultWebsiteDomainName, AuthenticationEndpoint = renewalParams.AuthenticationUri ?? new Uri(DefaultAuthenticationUri), ManagementEndpoint = renewalParams.AzureManagementEndpoint ?? new Uri(DefaultManagementEndpoint), TokenAudience = renewalParams.AzureTokenAudience ?? new Uri(DefaultAzureTokenAudienceService), }; var manager = CertificateManager.CreateKuduWebAppCertificateManager( azureEnvironment, new AcmeConfig { Host = renewalParams.Hosts[0], AlternateNames = renewalParams.Hosts.Skip(1).ToList(), RegistrationEmail = renewalParams.Email, RSAKeyLength = renewalParams.RsaKeyLength, PFXPassword = Convert.ToBase64String(pfxPassData), BaseUri = (renewalParams.AcmeBaseUri ?? new Uri(DefaultAcmeBaseUri)).ToString(), }, new CertificateServiceSettings { UseIPBasedSSL = renewalParams.UseIpBasedSsl }, new AuthProviderConfig()); var certificatesRenewed = 0; using (webSiteClient = await ArmHelper.GetWebSiteManagementClient(azureEnvironment)) { var isWebAppRunning = IsWebAppRunning(); if (!isWebAppRunning && !await StartWebApp()) { string errorMessage = string.Format("Could not start WebApp '{0}' to renew certificate", renewalParams.WebApp); Trace.TraceError(errorMessage); throw new WebAppException(renewalParams.WebApp, "Could not start WebApp"); } if (await HasCertificate()) { var result = await manager.RenewCertificate(false, renewalParams.RenewXNumberOfDaysBeforeExpiration); certificatesRenewed = result.Count; } else { var result = await manager.AddCertificate(); if (result != null) { certificatesRenewed = 1; } } if (!isWebAppRunning && !await StopWebApp()) { Trace.TraceWarning("Could not stop WebApp '{0}' after renewing certificate", renewalParams.WebApp); } } Trace.TraceInformation("SSL cert added successfully to '{0}'", renewalParams.WebApp); return(certificatesRenewed); }