public CertificateService(IOptions <CertificateServiceSettings> settings)
        {
            _settings = settings.Value;
            var certificatePath = Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), _settings.PfxCertificatePath);

            _intermediateCertificate = new X509Certificate2(certificatePath, _settings.PrivateKeyPassword);
        }
Exemple #2
0
        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 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 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);
        }