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()); } }
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 <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 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 AzureDnsAuthorizationChallengeProvider(IAzureEnvironment azureEnvironment) { this.httpClient = ArmHelper.GetHttpClient(azureEnvironment); }