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());
            }
        }
예제 #2
0
        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();
            }
        }
예제 #5
0
 public AzureDnsAuthorizationChallengeProvider(IAzureEnvironment azureEnvironment)
 {
     this.httpClient = ArmHelper.GetHttpClient(azureEnvironment);
 }