From d7e419a4b543e04a78cc75926f49129c233eb87f Mon Sep 17 00:00:00 2001 From: "Simon J.K. Pedersen" Date: Tue, 13 Nov 2018 22:25:41 +0100 Subject: [PATCH] #269, generate documentation in release. --- .../LetsEncrypt.SiteExtension.csproj | 4 +- .../CertificateManager.cs | 30 +++++++++--- .../LetsEncrypt.Azure.Core.csproj | 1 + .../CertificateManagerTest.cs | 47 ++++++++++++++++++- .../LetsEncrypt.SiteExtension.Test.csproj | 6 +++ LetsEncrypt.SiteExtension.Test/certArray.json | 33 +++++++++++++ .../certArrayWithValue.json | 35 ++++++++++++++ LetsEncrypt.WebAppOnly.nuspec | 2 +- LetsEncrypt.nuspec | 2 +- 9 files changed, 149 insertions(+), 11 deletions(-) create mode 100644 LetsEncrypt.SiteExtension.Test/certArray.json create mode 100644 LetsEncrypt.SiteExtension.Test/certArrayWithValue.json diff --git a/LetsEncrypt-SiteExtension/LetsEncrypt.SiteExtension.csproj b/LetsEncrypt-SiteExtension/LetsEncrypt.SiteExtension.csproj index b42c721..5f8e90d 100644 --- a/LetsEncrypt-SiteExtension/LetsEncrypt.SiteExtension.csproj +++ b/LetsEncrypt-SiteExtension/LetsEncrypt.SiteExtension.csproj @@ -23,6 +23,7 @@ + true @@ -42,6 +43,7 @@ TRACE prompt 4 + bin\LetsEncrypt.SiteExtension.XML @@ -219,8 +221,6 @@ - - diff --git a/LetsEncrypt.SiteExtension.Core/CertificateManager.cs b/LetsEncrypt.SiteExtension.Core/CertificateManager.cs index 4e284d3..0837c96 100644 --- a/LetsEncrypt.SiteExtension.Core/CertificateManager.cs +++ b/LetsEncrypt.SiteExtension.Core/CertificateManager.cs @@ -3,6 +3,7 @@ using Microsoft.Azure.Management.WebSites; using Microsoft.Azure.Management.WebSites.Models; using Newtonsoft.Json; +using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.Diagnostics; @@ -122,7 +123,7 @@ public async Task> RenewCertificate(bool skipInsta 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 certs = JsonConvert.DeserializeObject(body, JsonHelper.DefaultSerializationSettings); + IEnumerable certs = ExtractCertificates(body); var expiringCerts = certs.Where(s => s.ExpirationDate < DateTime.UtcNow.AddDays(renewXNumberOfDaysBeforeExpiration) && (s.Issuer.Contains("Let's Encrypt") || s.Issuer.Contains("Fake LE"))); @@ -143,24 +144,41 @@ public async Task> RenewCertificate(bool skipInsta } 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, + 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) { res.Add(await RequestAndInstallInternalAsync(target)); - } + } } return res; } - } + } + + internal static IEnumerable ExtractCertificates(string body) + { + + var json = JToken.Parse(body); + var certs = Enumerable.Empty(); + // Handle issue #269 + if (json.Type == JTokenType.Object && json["value"] != null) + { + certs = JsonConvert.DeserializeObject(json["value"].ToString(), JsonHelper.DefaultSerializationSettings); + } + else + { + certs = JsonConvert.DeserializeObject(body, JsonHelper.DefaultSerializationSettings); + } + return certs; + } internal CertificateInstallModel RequestAndInstallInternal(IAcmeConfig config) { diff --git a/LetsEncrypt.SiteExtension.Core/LetsEncrypt.Azure.Core.csproj b/LetsEncrypt.SiteExtension.Core/LetsEncrypt.Azure.Core.csproj index 5bc524a..3b32a8e 100644 --- a/LetsEncrypt.SiteExtension.Core/LetsEncrypt.Azure.Core.csproj +++ b/LetsEncrypt.SiteExtension.Core/LetsEncrypt.Azure.Core.csproj @@ -30,6 +30,7 @@ TRACE prompt 4 + bin\LetsEncrypt.Azure.Core.XML true diff --git a/LetsEncrypt.SiteExtension.Test/CertificateManagerTest.cs b/LetsEncrypt.SiteExtension.Test/CertificateManagerTest.cs index e9f42e6..f05af36 100644 --- a/LetsEncrypt.SiteExtension.Test/CertificateManagerTest.cs +++ b/LetsEncrypt.SiteExtension.Test/CertificateManagerTest.cs @@ -5,6 +5,12 @@ using LetsEncrypt.Azure.Core.Models; using LetsEncrypt.Azure.Core; using LetsEncrypt.Azure.Core.Services; +using System.Collections.Generic; +using System.Security; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using System.Net; +using System.IO; namespace LetsEncrypt.SiteExtension.Test { @@ -18,7 +24,7 @@ public async Task RenewCertificateTest() { var result = await new CertificateManager(new AppSettingsAuthConfig()).RenewCertificate(); - Assert.AreNotEqual(0, result.Count()); + Assert.AreEqual(0, result.Count()); } [TestCategory("Integration")] @@ -33,6 +39,7 @@ public async Task RenewCertificateConstructorTest() var result = await mgr.RenewCertificate(renewXNumberOfDaysBeforeExpiration: 200); Assert.AreNotEqual(0, result.Count()); + ValidateCertificate(result, "https://letsencrypt.sjkp.dk"); } [TestCategory("Integration")] @@ -70,6 +77,7 @@ public async Task AddCertificateDnsChallengeTest() var result = await mgr.AddCertificate(); Assert.IsNotNull(result); + ValidateCertificate(new[] { result }, "https://letsencrypt.ai4bots.com"); } [TestCategory("Integration")] @@ -89,5 +97,42 @@ public async Task RequestCertificateDnsChallengeTest() Assert.IsTrue(res.CertificateInfo.Certificate.Subject.Contains("ai4bots.com")); } + + [DeploymentItem("certArray.json")] + [DeploymentItem("certArrayWithValue.json")] + [TestMethod] + public void ExtractCertificates() + { + var t1 = File.ReadAllText("certArray.json"); + var t2 = File.ReadAllText("certArrayWithValue.json"); + var res1 = CertificateManager.ExtractCertificates(t1); + var res2 = CertificateManager.ExtractCertificates(t2); + + Assert.AreEqual("A19D760D4D50552DA48B1D493738BD754E5EA8DA", res1.FirstOrDefault().Thumbprint); + Assert.AreEqual("A19D760D4D50552DA48B1D493738BD754E5EA8DA", res2.FirstOrDefault().Thumbprint); + } + + + private void ValidateCertificate(IEnumerable certs, string uri) + { + //Do webrequest to get info on secure site + HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); + HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + response.Close(); + + //retrieve the ssl cert and assign it to an X509Certificate object + X509Certificate cert = request.ServicePoint.Certificate; + + //convert the X509Certificate to an X509Certificate2 object by passing it into the constructor + X509Certificate2 cert2 = new X509Certificate2(cert); + + string cn = cert2.Issuer; + Assert.AreEqual("CN=Fake LE Intermediate X1", cn); + string tb = cert2.Thumbprint; + Assert.AreEqual(certs.FirstOrDefault().CertificateInfo.Certificate.Thumbprint, tb); + string cedate = cert2.GetExpirationDateString(); + string cpub = cert2.GetPublicKeyString(); + } } } + diff --git a/LetsEncrypt.SiteExtension.Test/LetsEncrypt.SiteExtension.Test.csproj b/LetsEncrypt.SiteExtension.Test/LetsEncrypt.SiteExtension.Test.csproj index 7dae30e..9d78140 100644 --- a/LetsEncrypt.SiteExtension.Test/LetsEncrypt.SiteExtension.Test.csproj +++ b/LetsEncrypt.SiteExtension.Test/LetsEncrypt.SiteExtension.Test.csproj @@ -142,6 +142,12 @@ Always + + Always + + + Always + Always diff --git a/LetsEncrypt.SiteExtension.Test/certArray.json b/LetsEncrypt.SiteExtension.Test/certArray.json new file mode 100644 index 0000000..7ac5cec --- /dev/null +++ b/LetsEncrypt.SiteExtension.Test/certArray.json @@ -0,0 +1,33 @@ +[ + { + "id": "/subscriptions/3f09c367-93e0-4b61-bbe5-dcb5c686bf8a/resourceGroups/LetsEncrypt-SiteExtension/providers/Microsoft.Web/certificates/letsencrypt.sjkp.dk-A19D760D4D50552DA48B1D493738BD754E5EA8DA", + "name": "letsencrypt.sjkp.dk-A19D760D4D50552DA48B1D493738BD754E5EA8DA", + "type": "Microsoft.Web/certificates", + "location": "West US", + "properties": { + "friendlyName": "CN=letsencrypt.sjkp.dk", + "subjectName": "letsencrypt.sjkp.dk", + "hostNames": [ + "letsencrypt.sjkp.dk" + ], + "pfxBlob": null, + "siteName": null, + "selfLink": null, + "issuer": "Fake LE Intermediate X1", + "issueDate": "2018-11-13T20:19:24+01:00", + "expirationDate": "2019-02-11T20:19:24+01:00", + "password": null, + "thumbprint": "A19D760D4D50552DA48B1D493738BD754E5EA8DA", + "valid": null, + "toDelete": null, + "cerBlob": null, + "publicKeyHash": null, + "hostingEnvironment": null, + "hostingEnvironmentProfile": null, + "keyVaultSecretStatus": "Initialized", + "webSpace": "LetsEncrypt-SiteExtension-WestUSwebspace", + "serverFarmId": null, + "tags": null + } + } +] diff --git a/LetsEncrypt.SiteExtension.Test/certArrayWithValue.json b/LetsEncrypt.SiteExtension.Test/certArrayWithValue.json new file mode 100644 index 0000000..f9d09e4 --- /dev/null +++ b/LetsEncrypt.SiteExtension.Test/certArrayWithValue.json @@ -0,0 +1,35 @@ +{ + "value": [ + { + "id": "/subscriptions/3f09c367-93e0-4b61-bbe5-dcb5c686bf8a/resourceGroups/LetsEncrypt-SiteExtension/providers/Microsoft.Web/certificates/letsencrypt.sjkp.dk-A19D760D4D50552DA48B1D493738BD754E5EA8DA", + "name": "letsencrypt.sjkp.dk-A19D760D4D50552DA48B1D493738BD754E5EA8DA", + "type": "Microsoft.Web/certificates", + "location": "West US", + "properties": { + "friendlyName": "CN=letsencrypt.sjkp.dk", + "subjectName": "letsencrypt.sjkp.dk", + "hostNames": [ + "letsencrypt.sjkp.dk" + ], + "pfxBlob": null, + "siteName": null, + "selfLink": null, + "issuer": "Fake LE Intermediate X1", + "issueDate": "2018-11-13T20:19:24+01:00", + "expirationDate": "2019-02-11T20:19:24+01:00", + "password": null, + "thumbprint": "A19D760D4D50552DA48B1D493738BD754E5EA8DA", + "valid": null, + "toDelete": null, + "cerBlob": null, + "publicKeyHash": null, + "hostingEnvironment": null, + "hostingEnvironmentProfile": null, + "keyVaultSecretStatus": "Initialized", + "webSpace": "LetsEncrypt-SiteExtension-WestUSwebspace", + "serverFarmId": null, + "tags": null + } + } + ] +} \ No newline at end of file diff --git a/LetsEncrypt.WebAppOnly.nuspec b/LetsEncrypt.WebAppOnly.nuspec index daeb051..90e12b8 100644 --- a/LetsEncrypt.WebAppOnly.nuspec +++ b/LetsEncrypt.WebAppOnly.nuspec @@ -3,7 +3,7 @@ letsencrypt.webapponly Azure Let's Encrypt (No Web Jobs) - 0.8.7 + 0.8.8 SJKP http://opensource.org/licenses/Apache-2.0 https://github.com/sjkp/letsencrypt-siteextension diff --git a/LetsEncrypt.nuspec b/LetsEncrypt.nuspec index 98608ae..28ec4a5 100644 --- a/LetsEncrypt.nuspec +++ b/LetsEncrypt.nuspec @@ -3,7 +3,7 @@ letsencrypt Azure Let's Encrypt - 0.8.7 + 0.8.8 SJKP http://opensource.org/licenses/Apache-2.0 https://github.com/sjkp/letsencrypt-siteextension