private static LetsencryptService GetDnsRenewalService(RenewalParameters renewalParams, IAzureDnsEnvironment azureDnsEnvironment, AzureWebAppEnvironment webAppEnvironment) { return(new LetsencryptService( new AcmeClient( new AzureDnsProvider( new AzureDnsSettings( azureDnsEnvironment.ResourceGroupName, azureDnsEnvironment.ZoneName, GetAzureServicePrincipal(azureDnsEnvironment), GetAzureSubscription(azureDnsEnvironment), azureDnsEnvironment.RelativeRecordSetName)), new DnsLookupService(new Logger <DnsLookupService>(s_loggerFactory)), new NullCertificateStore(), new Logger <AcmeClient>(s_loggerFactory)), new NullCertificateStore(), new AzureWebAppService( new[] { new AzureWebAppSettings( webAppEnvironment.WebAppName, webAppEnvironment.ResourceGroupName, GetAzureServicePrincipal(webAppEnvironment), GetAzureSubscription(webAppEnvironment), webAppEnvironment.SiteSlotName, webAppEnvironment.ServicePlanResourceGroupName, renewalParams.UseIpBasedSsl), }, new Logger <AzureWebAppService>(s_loggerFactory)), new Logger <LetsencryptService>(s_loggerFactory))); }
private static async Task <bool> CheckCertAddition( RenewalParameters renewalParams, AzureWebAppEnvironment webAppEnvironment, AcmeConfig acmeConfig, bool staging) { if (renewalParams.RenewXNumberOfDaysBeforeExpiration <= 0) { return(true); } var letsEncryptHostNames = await CertificateHelper.GetLetsEncryptHostNames(webAppEnvironment, staging).ConfigureAwait(false); Trace.TraceInformation("Let's Encrypt host names (staging: {0}): {1}", staging, String.Join(", ", letsEncryptHostNames)); ICollection <string> missingHostNames = acmeConfig.Hostnames.Except(letsEncryptHostNames, StringComparer.OrdinalIgnoreCase).ToArray(); if (missingHostNames.Count > 0) { Trace.TraceInformation( "Detected host name(s) with no associated Let's Encrypt certificates, will add a new certificate: {0}", String.Join(", ", missingHostNames)); return(true); } Trace.TraceInformation("All host names associated with Let's Encrypt certificates, will perform cert renewal"); return(false); }
private static IDnsProvider GetDnsProvider(RenewalParameters renewalParams) { var azureDnsEnvironment = GetAzureDnsEnvironment(renewalParams); if (azureDnsEnvironment != null) { return(new AzureDnsProvider( new AzureDnsSettings( azureDnsEnvironment.ResourceGroupName, azureDnsEnvironment.ZoneName, GetAzureServicePrincipal(azureDnsEnvironment), GetAzureSubscription(azureDnsEnvironment), azureDnsEnvironment.RelativeRecordSetName))); } if (!string.IsNullOrEmpty(renewalParams.GoDaddyDnsEnvironmentParams?.ApiKey) && !string.IsNullOrEmpty(renewalParams.GoDaddyDnsEnvironmentParams?.ApiSecret) && !string.IsNullOrEmpty(renewalParams.GoDaddyDnsEnvironmentParams?.Domain) && !string.IsNullOrEmpty(renewalParams.GoDaddyDnsEnvironmentParams?.ShopperId)) { return(new CustomGoDaddyDnsProvider( new CustomGoDaddyDnsProvider.GoDaddyDnsSettings() { ApiKey = renewalParams.GoDaddyDnsEnvironmentParams.ApiKey, ApiSecret = renewalParams.GoDaddyDnsEnvironmentParams.ApiSecret, Domain = renewalParams.GoDaddyDnsEnvironmentParams.Domain, ShopperId = renewalParams.GoDaddyDnsEnvironmentParams.ShopperId, })); } Trace.TraceInformation($"Either {nameof(renewalParams.GoDaddyDnsEnvironmentParams.ApiKey)} or {nameof(renewalParams.GoDaddyDnsEnvironmentParams.ApiSecret)} or {nameof(renewalParams.GoDaddyDnsEnvironmentParams.Domain)} or {nameof(renewalParams.GoDaddyDnsEnvironmentParams.ShopperId)} are null for {GetWebAppFullName(renewalParams)}, will not use GoDaddy DNS challenge"); return(null); }
private static readonly RNGCryptoServiceProvider s_randomGenerator = new RNGCryptoServiceProvider(); // thread-safe public Task Renew(RenewalParameters renewalParams) { if (renewalParams == null) { throw new ArgumentNullException(nameof(renewalParams)); } return(RenewCore(renewalParams)); }
private static readonly RNGCryptoServiceProvider s_randomGenerator = new RNGCryptoServiceProvider(); // thread-safe public async Task Renew(RenewalParameters renewalParams) { if (renewalParams == null) { throw new ArgumentNullException(nameof(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}'...", renewalParams.WebApp); var manager = CertificateManager.CreateKuduWebAppCertificateManager( new AzureWebAppEnvironment( renewalParams.TenantId, renewalParams.SubscriptionId, renewalParams.ClientId, renewalParams.ClientSecret, renewalParams.ResourceGroup, renewalParams.WebApp, renewalParams.ServicePlanResourceGroup, renewalParams.SiteSlotName) { AzureWebSitesDefaultDomainName = renewalParams.AzureDefaultWebsiteDomainName ?? DefaultWebsiteDomainName, AuthenticationEndpoint = renewalParams.AuthenticationUri ?? new Uri(DefaultAuthenticationUri), ManagementEndpoint = renewalParams.AzureManagementEndpoint ?? new Uri(DefaultManagementEndpoint), TokenAudience = renewalParams.AzureTokenAudience ?? new Uri(DefaultAzureTokenAudienceService) }, 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()); if (renewalParams.RenewXNumberOfDaysBeforeExpiration > 0) { await manager.RenewCertificate(false, renewalParams.RenewXNumberOfDaysBeforeExpiration); } else { await manager.AddCertificate(); } Trace.TraceInformation("SSL cert added successfully to '{0}'", renewalParams.WebApp); }
private static async Task RenewCore(RenewalParameters renewalParams) { Trace.TraceInformation("Generating SSL certificate with parameters: {0}", renewalParams); var acmeConfig = GetAcmeConfig(renewalParams); var webAppEnvironment = GetWebAppEnvironment(renewalParams); var certificateServiceSettings = new CertificateServiceSettings { UseIPBasedSSL = renewalParams.UseIpBasedSsl }; var azureDnsEnvironment = GetAzureDnsEnvironment(renewalParams); if (azureDnsEnvironment != null) { throw new ConfigurationErrorsException("Azure DNS challenge currently not supported"); } var manager = CertificateManager.CreateKuduWebAppCertificateManager(webAppEnvironment, acmeConfig, certificateServiceSettings, new AuthProviderConfig()); Trace.TraceInformation("Adding SSL cert for '{0}'...", GetWebAppFullName(renewalParams)); bool addNewCert = true; if (renewalParams.RenewXNumberOfDaysBeforeExpiration > 0) { var staging = acmeConfig.BaseUri.Contains("staging", StringComparison.OrdinalIgnoreCase); var letsEncryptHostNames = await CertificateHelper.GetLetsEncryptHostNames(webAppEnvironment, staging); Trace.TraceInformation("Let's Encrypt host names (staging: {0}): {1}", staging, String.Join(", ", letsEncryptHostNames)); ICollection <string> missingHostNames = acmeConfig.Hostnames.Except(letsEncryptHostNames, StringComparer.OrdinalIgnoreCase).ToArray(); if (missingHostNames.Count > 0) { Trace.TraceInformation( "Detected host name(s) with no associated Let's Encrypt certificates, will add a new certificate: {0}", String.Join(", ", missingHostNames)); } else { Trace.TraceInformation("All host names associated with Let's Encrypt certificates, will perform cert renewal"); addNewCert = false; } } if (addNewCert) { await manager.AddCertificate(); } else { await manager.RenewCertificate(false, renewalParams.RenewXNumberOfDaysBeforeExpiration); } Trace.TraceInformation("Let's Encrypt SSL certs & bindings renewed for '{0}'", renewalParams.WebApp); }
private static AcmeConfig GetAcmeConfig(RenewalParameters renewalParams, string pfxPassData) { Trace.TraceInformation("Generating secure PFX password for '{0}'...", renewalParams.WebApp); return(new AcmeConfig { Host = renewalParams.Hosts[0], AlternateNames = renewalParams.Hosts.Skip(1).ToList(), RegistrationEmail = renewalParams.Email, RSAKeyLength = renewalParams.RsaKeyLength, PFXPassword = pfxPassData, BaseUri = (renewalParams.AcmeBaseUri ?? new Uri(DefaultAcmeBaseUri)).ToString(), }); }
private static AcmeConfig GetAcmeConfig(RenewalParameters renewalParams) { Trace.TraceInformation("Generating secure PFX password for '{0}'...", renewalParams.WebApp); var pfxPassData = new byte[32]; s_randomGenerator.GetBytes(pfxPassData); return(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(), }); }
private static readonly RNGCryptoServiceProvider s_randomGenerator = new RNGCryptoServiceProvider(); // thread-safe public void Renew(RenewalParameters renewParams) { if (renewParams == null) { throw new ArgumentNullException(nameof(renewParams)); } Trace.TraceInformation("Generating SSL certificate with parameters: {0}", renewParams); Trace.TraceInformation("Generating secure PFX password for '{0}'...", renewParams.WebApp); byte[] pfxPassData = new byte[32]; s_randomGenerator.GetBytes(pfxPassData); Trace.TraceInformation("Adding SSL cert for '{0}'...", renewParams.WebApp); var manager = new CertificateManager( new AzureEnvironment( renewParams.TenantId, renewParams.SubscriptionId, renewParams.ClientId, renewParams.ClientSecret, renewParams.ResourceGroup, renewParams.WebApp, renewParams.ServicePlanResourceGroup, renewParams.SiteSlotName), new AcmeConfig { Host = renewParams.Hosts[0], AlternateNames = renewParams.Hosts.Skip(1).ToList(), RegistrationEmail = renewParams.Email, RSAKeyLength = renewParams.RsaKeyLength, PFXPassword = Convert.ToBase64String(pfxPassData), #pragma warning disable S1075 BaseUri = (renewParams.AcmeBaseUri ?? new Uri("https://acme-v01.api.letsencrypt.org/")).ToString() #pragma warning restore S1075 }, new CertificateServiceSettings { UseIPBasedSSL = renewParams.UseIpBasedSsl }, new AuthProviderConfig()); manager.AddCertificate(); Trace.TraceInformation("SSL cert added successfully to '{0}'", renewParams.WebApp); }
private static async Task RenewCore(RenewalParameters renewalParams) { Trace.TraceInformation("Adding / renewing SSL cert for '{0}' with parameters: {1}", GetWebAppFullName(renewalParams), renewalParams); var acmeConfig = GetAcmeConfig(renewalParams, CertificateHelper.GenerateSecurePassword()); var webAppEnvironment = GetWebAppEnvironment(renewalParams); var certificateServiceSettings = new CertificateServiceSettings { UseIPBasedSSL = renewalParams.UseIpBasedSsl }; var azureDnsEnvironment = GetAzureDnsEnvironment(renewalParams); bool staging = acmeConfig.BaseUri.Contains("staging", StringComparison.OrdinalIgnoreCase); if (azureDnsEnvironment != null) { await GetDnsRenewalService(renewalParams, azureDnsEnvironment, webAppEnvironment).Run( new AcmeDnsRequest { AcmeEnvironment = staging ? (AcmeEnvironment) new LetsEncryptStagingV2() : new LetsEncryptV2(), RegistrationEmail = acmeConfig.RegistrationEmail, Host = acmeConfig.Host, PFXPassword = CertificateHelper.GenerateSecurePassword(), CsrInfo = new CsrInfo(), }, renewalParams.RenewXNumberOfDaysBeforeExpiration).ConfigureAwait(false); } else { var manager = CertificateManager.CreateKuduWebAppCertificateManager(webAppEnvironment, acmeConfig, certificateServiceSettings, new AuthProviderConfig()); var addNewCert = await CheckCertAddition(renewalParams, webAppEnvironment, acmeConfig, staging).ConfigureAwait(false); if (addNewCert) { await manager.AddCertificate().ConfigureAwait(false); } else { await manager.RenewCertificate(false, renewalParams.RenewXNumberOfDaysBeforeExpiration).ConfigureAwait(false); } } Trace.TraceInformation("Let's Encrypt SSL certs & bindings renewed for '{0}'", renewalParams.WebApp); }
private static AzureWebAppEnvironment GetWebAppEnvironment(RenewalParameters renewalParams) { Debug.Assert(renewalParams.WebAppEnvironmentParams?.SubscriptionId != null, "renewalParams.WebAppEnvironmentParams?.SubscriptionId != null"); Debug.Assert(renewalParams.WebAppEnvironmentParams?.ClientId != null, "renewalParams.WebAppEnvironmentParams?.ClientId != null"); return(new AzureWebAppEnvironment( renewalParams.WebAppEnvironmentParams.TenantId, renewalParams.WebAppEnvironmentParams.SubscriptionId.Value, renewalParams.WebAppEnvironmentParams.ClientId.Value, renewalParams.WebAppEnvironmentParams.ClientSecret, renewalParams.WebAppEnvironmentParams.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), }); }
private static IAzureDnsEnvironment GetAzureDnsEnvironment(RenewalParameters renewalParams) { var zoneName = renewalParams.AzureDnsZoneName; var relativeRecordSetName = renewalParams.AzureDnsRelativeRecordSetName; if (zoneName == null || relativeRecordSetName == null) { Trace.TraceInformation($"Either {nameof(zoneName)} or {nameof(relativeRecordSetName)} are null for {GetWebAppFullName(renewalParams)}, will not use Azure DNS challenge"); return(null); } Debug.Assert(renewalParams.AzureDnsEnvironmentParams?.SubscriptionId != null, "renewalParams.AzureDnsEnvironmentParams?.SubscriptionId != null"); Debug.Assert(renewalParams.AzureDnsEnvironmentParams?.ClientId != null, "renewalParams.AzureDnsEnvironmentParams?.ClientId != null"); return(new AzureDnsEnvironment( renewalParams.AzureDnsEnvironmentParams.TenantId, renewalParams.AzureDnsEnvironmentParams.SubscriptionId.Value, renewalParams.AzureDnsEnvironmentParams.ClientId.Value, renewalParams.AzureDnsEnvironmentParams.ClientSecret, renewalParams.AzureDnsEnvironmentParams.ResourceGroup, zoneName, relativeRecordSetName)); }
private static string GetWebAppFullName(RenewalParameters renewalParams) { return(String.Format(CultureInfo.InvariantCulture, "{0}{1}", renewalParams.WebApp, renewalParams.GroupName == null ? String.Empty : $"[{renewalParams.GroupName}]")); }
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); }
private static async Task 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}]"); var certServiceSettings = new CertificateServiceSettings { UseIPBasedSSL = renewalParams.UseIpBasedSsl }; var azureWebAppEnvironment = new AzureWebAppEnvironment( renewalParams.TenantId, renewalParams.SubscriptionId, renewalParams.ClientId, renewalParams.ClientSecret, renewalParams.ResourceGroup, renewalParams.WebApp, renewalParams.ServicePlanResourceGroup, renewalParams.SiteSlotName) { AzureWebSitesDefaultDomainName = renewalParams.AzureDefaultWebsiteDomainName ?? DefaultWebsiteDomainName, AuthenticationEndpoint = renewalParams.AuthenticationUri ?? new Uri(DefaultAuthenticationUri), ManagementEndpoint = renewalParams.AzureManagementEndpoint ?? new Uri(DefaultManagementEndpoint), TokenAudience = renewalParams.AzureTokenAudience ?? new Uri(DefaultAzureTokenAudienceService) }; AzureWebAppEnvironment otherAzureWebAppEnvironment = null; WebAppCertificateService otherWebAppCertificateService = null; if (!string.IsNullOrEmpty(renewalParams.OtherWebAppResourceGroup) && !string.IsNullOrEmpty(renewalParams.OtherWebApp)) { otherAzureWebAppEnvironment = new AzureWebAppEnvironment( renewalParams.TenantId, renewalParams.SubscriptionId, renewalParams.ClientId, renewalParams.ClientSecret, renewalParams.OtherWebAppResourceGroup, renewalParams.OtherWebApp, renewalParams.ServicePlanResourceGroup, renewalParams.OtherSlotName) { AzureWebSitesDefaultDomainName = renewalParams.AzureDefaultWebsiteDomainName ?? DefaultWebsiteDomainName, AuthenticationEndpoint = renewalParams.AuthenticationUri ?? new Uri(DefaultAuthenticationUri), ManagementEndpoint = renewalParams.AzureManagementEndpoint ?? new Uri(DefaultManagementEndpoint), TokenAudience = renewalParams.AzureTokenAudience ?? new Uri(DefaultAzureTokenAudienceService) }; otherWebAppCertificateService = new WebAppCertificateService(otherAzureWebAppEnvironment, certServiceSettings); } var azureStorageEnvironment = new AzureStorageEnvironment( renewalParams.TenantId, renewalParams.SubscriptionId, renewalParams.ClientId, renewalParams.ClientSecret, renewalParams.ResourceGroup, renewalParams.StorageConnectionString, renewalParams.StorageContainer); var webAppCertificateService = new WebAppCertificateService(azureWebAppEnvironment, certServiceSettings); var manager = new CertificateManager( azureWebAppEnvironment, 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() }, webAppCertificateService, new AzureStorageFileSystemAuthorizationChallengeProvider(azureStorageEnvironment)); if (renewalParams.RenewXNumberOfDaysBeforeExpiration > 0) { await manager.RenewCertificate(false, renewalParams.RenewXNumberOfDaysBeforeExpiration); } else { var res = await manager.AddCertificate(); webAppCertificateService.RemoveExpired(); otherWebAppCertificateService?.Install(res); otherWebAppCertificateService?.RemoveExpired(); } Trace.TraceInformation("SSL cert added successfully to '{0}'", renewalParams.WebApp); }