From 9421142fc7547919bd22df98409148df67e418eb Mon Sep 17 00:00:00 2001 From: Mathias Raacke Date: Mon, 23 Nov 2015 18:55:07 +0100 Subject: [PATCH] added command line argument to configure registration contact added command line argument to configure agreement uri removed hard coded contact email improved unit tests --- .vs/ACME.net/v14/.suo | Bin 314368 -> 347648 bytes src/Oocx.ACME.Console/AcmeProcess.cs | 9 +- src/Oocx.ACME.Console/Options.cs | 8 +- src/Oocx.ACME.Tests/ClientTests.cs | 71 +++- .../FakeHttp/FakeHttpMessageHandler.cs | 59 ++++ .../FakeHttp/FakeRequestConfiguration.cs | 74 ++++ .../FakeHttp/HttpRequestMessageAssertions.cs | 48 +++ .../FakeHttp/PreventDisposeContentWrapper.cs | 51 +++ src/Oocx.ACME.Tests/project.json | 3 +- src/Oocx.ACME.Tests/project.lock.json | 326 ------------------ src/Oocx.ACME/Client/AcmeClient.cs | 12 +- src/Oocx.ACME/Client/IAcmeClient.cs | 4 +- 12 files changed, 309 insertions(+), 356 deletions(-) create mode 100644 src/Oocx.ACME.Tests/FakeHttp/FakeHttpMessageHandler.cs create mode 100644 src/Oocx.ACME.Tests/FakeHttp/FakeRequestConfiguration.cs create mode 100644 src/Oocx.ACME.Tests/FakeHttp/HttpRequestMessageAssertions.cs create mode 100644 src/Oocx.ACME.Tests/FakeHttp/PreventDisposeContentWrapper.cs diff --git a/.vs/ACME.net/v14/.suo b/.vs/ACME.net/v14/.suo index a5135ae44506ee3c34fbe626136345eb7eec4e16..f64056c3668446d4e70650169bb2bf5895a2efdf 100644 GIT binary patch delta 28997 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 diff --git a/src/Oocx.ACME.Console/AcmeProcess.cs b/src/Oocx.ACME.Console/AcmeProcess.cs index 68d3408..572b92f 100644 --- a/src/Oocx.ACME.Console/AcmeProcess.cs +++ b/src/Oocx.ACME.Console/AcmeProcess.cs @@ -164,7 +164,7 @@ private async Task AuthorizeForDomain(string domain) private async Task RegisterWithServer() { - var registration = await client.RegisterAsync(options.AcceptTermsOfService); + var registration = await client.RegisterAsync(options.AcceptTermsOfService ? options.TermsOfServiceUri : null, options.Contact); Info($"Terms of service: {registration.Agreement}"); Verbose($"Created at: {registration.CreatedAt}"); Verbose($"Id: {registration.Id}"); @@ -174,7 +174,12 @@ private async Task RegisterWithServer() if (!string.IsNullOrWhiteSpace(registration.Location) && options.AcceptTermsOfService) { Info("accepting terms of service"); - await client.UpdateRegistrationAsync(registration.Location, registration.Agreement); + if (!string.Equals(registration.Agreement, options.TermsOfServiceUri)) + { + Error($"Cannot accept terms of service. The terms of service uri is '{registration.Agreement}', expected it to be '{options.TermsOfServiceUri}'."); + return; + } + await client.UpdateRegistrationAsync(registration.Location, registration.Agreement, options.Contact); } } diff --git a/src/Oocx.ACME.Console/Options.cs b/src/Oocx.ACME.Console/Options.cs index 1ab8e09..465893d 100644 --- a/src/Oocx.ACME.Console/Options.cs +++ b/src/Oocx.ACME.Console/Options.cs @@ -14,9 +14,12 @@ public class Options [Value(0, HelpText = "The names of the domains for which you want to request a certificate.", Required = true, MetaName = "domains")] public IEnumerable Domains { get; set; } - [Option('a', "acceptTOS", HelpText = "Accept the terms of service of the ACME server")] + [Option('a', "acceptTermsOfService", HelpText = "Accept the terms of service of the ACME server")] public bool AcceptTermsOfService { get; set; } + [Option('t', "termsOfServiceUri", HelpText = "The uri of the terms of service that you accept.", Default = "https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf")] + public string TermsOfServiceUri { get; set; } + [Option('i', "ignoreSSLErrors", HelpText = "Ignore SSL certificate errors for the HTTPS connection to the ACME server (useful for debugging messages with fiddler)")] public bool IgnoreSSLCertificateErrors { get; set; } @@ -43,5 +46,8 @@ public class Options [Option('b', "iisBinding", HelpText = "The IIS binding that should be configured to use the new certificate. Syntax: ip:port:hostname, for example '*:443:www.example.com' (used with --serverConfigurationProvider iis). If you do not specifiy a binding, the provider will try to find a matching binding. It will create a binding if no matching binding exists.")] public string IISBinidng { get; set; } + + [Option('m', "contact", HelpText = "The contact information for the registration request. Example: mailto:you@example.com")] + public string[] Contact { get; set; } } } \ No newline at end of file diff --git a/src/Oocx.ACME.Tests/ClientTests.cs b/src/Oocx.ACME.Tests/ClientTests.cs index 6c2063b..f374fa2 100644 --- a/src/Oocx.ACME.Tests/ClientTests.cs +++ b/src/Oocx.ACME.Tests/ClientTests.cs @@ -1,29 +1,32 @@ using System; -using System.Collections.Generic; +using System.Linq; using System.Net; using System.Net.Http; -using System.Net.Http.Formatting; using System.Security.Cryptography; using System.Threading.Tasks; using FluentAssertions; using Oocx.ACME.Client; using Oocx.ACME.Protocol; -using WorldDomination.Net.Http; +using Oocx.ACME.Tests.FakeHttp; using Xunit; namespace Oocx.ACME.Tests { public class ClientTests { + + [Fact] public async Task Should_get_a_Directory_object_from_the_default_endpoint() { // Arrange + var http = new FakeHttpMessageHandler("http://baseaddress/"); var directory = new Directory(); - var response = new HttpResponseMessage(HttpStatusCode.OK) {Content = new ObjectContent(directory, new JsonMediaTypeFormatter()) }; - response.Headers.Add("Replay-Nonce", "nonce"); - var handler = new FakeHttpMessageHandler("http://baseaddress/directory", response); - var client = new HttpClient(handler) { BaseAddress = new Uri("http://baseAddress")}; + + var client = + http.RequestTo("directory").Returns(directory).WithNonce("nonce") + .GetHttpClient(); + var sut = new AcmeClient(client, new RSACryptoServiceProvider()); // Act @@ -37,28 +40,62 @@ public async Task Should_get_a_Directory_object_from_the_default_endpoint() public async Task Should_post_a_valid_Registration_message() { // Arrange + var http = new FakeHttpMessageHandler("http://baseaddress/"); var directory = new Directory() { NewRegistration = new Uri("http://baseaddress/registration")}; - var response1 = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ObjectContent(directory, new JsonMediaTypeFormatter()) }; - response1.Headers.Add("Replay-Nonce", "nonce"); - var registration = new RegistrationResponse(); - var response2 = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ObjectContent(registration, new JsonMediaTypeFormatter()) }; - response2.Headers.Add("Replay-Nonce", "nonce"); - var handler = new FakeHttpMessageHandler(new Dictionary() + var client = + http.RequestTo("directory").Returns(directory).WithNonce("nonce"). + RequestTo("registration").Returns(registration).WithNonce("nonce"). + GetHttpClient(); + + var sut = new AcmeClient(client, new RSACryptoServiceProvider()); + + // Act + var registrationResponse = await sut.RegisterAsync("agreementUri", new []{ "mailto:admin@example.com"}); + + // Assert + registrationResponse.Should().NotBeNull(); + http.ReceivedRequestsTo("directory").Single().HasMethod(HttpMethod.Get); + http.ReceivedRequestsTo("registration").Single().HasMethod(HttpMethod.Post).HasJwsPayload(r => { - {"http://baseaddress/directory", response1 }, - {"http://baseaddress/registration", response2 } + r.Agreement.Should().Be("agreementUri"); + r.Contact.Should().Contain("mailto:admin@example.com"); }); + } + + [Fact] + public async Task Should_POST_to_get_registration_details_if_the_registration_already_exists() + { + // Arrange + var http = new FakeHttpMessageHandler("http://baseaddress/"); + var directory = new Directory() { NewRegistration = new Uri("http://baseaddress/registration") }; + var registration = new RegistrationResponse(); + + var client = + http.RequestTo("directory").Returns(directory).WithNonce("nonce"). + RequestTo("registration").Returns(new Problem(), "application/problem+json").HasStatusCode(HttpStatusCode.Conflict).WithHeader("Location", "http://baseaddress/existingreguri").WithNonce("nonce"). + RequestTo("existingreguri").Returns(registration).WithNonce("nonce"). + GetHttpClient(); - var client = new HttpClient(handler) { BaseAddress = new Uri("http://baseAddress") }; var sut = new AcmeClient(client, new RSACryptoServiceProvider()); // Act - var registrationResponse = await sut.RegisterAsync(false); + var registrationResponse = await sut.RegisterAsync("agreementUri", new[] { "mailto:admin@example.com" }); // Assert registrationResponse.Should().NotBeNull(); + http.ReceivedRequestsTo("directory").Single().HasMethod(HttpMethod.Get); + http.ReceivedRequestsTo("registration").Single().HasMethod(HttpMethod.Post).HasJwsPayload(r => + { + r.Agreement.Should().Be("agreementUri"); + r.Contact.Should().Contain("mailto:admin@example.com"); + }); + http.ReceivedRequestsTo("existingreguri").Single().HasMethod(HttpMethod.Post).HasJwsPayload(r => + { + r.Agreement.Should().BeNull(); + r.Contact.Should().BeNull(); + }); } } } \ No newline at end of file diff --git a/src/Oocx.ACME.Tests/FakeHttp/FakeHttpMessageHandler.cs b/src/Oocx.ACME.Tests/FakeHttp/FakeHttpMessageHandler.cs new file mode 100644 index 0000000..57e359b --- /dev/null +++ b/src/Oocx.ACME.Tests/FakeHttp/FakeHttpMessageHandler.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; +using FluentAssertions.Execution; + +namespace Oocx.ACME.Tests.FakeHttp +{ + public class FakeHttpMessageHandler : HttpMessageHandler + { + private readonly Queue requestConfigurations = new Queue(); + + private readonly List actualRequests = new List(); + + public string BaseAddress { get; } + + public FakeHttpMessageHandler(string baseAddress) + { + this.BaseAddress = baseAddress; + } + + public FakeRequestConfiguration RequestTo(string uri) + { + return new FakeRequestConfiguration(this) { Uri = BaseAddress + uri }; + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + request.Content = await PreventDisposeContentWrapper.CreateWrapperAsync(request.Content); + + actualRequests.Add(request); + + var expected = requestConfigurations.Dequeue(); + if (!request.RequestUri.Equals(new Uri(expected.Uri, UriKind.RelativeOrAbsolute))) + { + throw new AssertionFailedException($"expected request to '{expected.Uri}', but got request to '{request.RequestUri}'"); + } + + return expected.GetResponseMessage(); + } + + public HttpRequestMessage[] ReceivedRequestsTo(string uri) + { + var requests = actualRequests.Where(r => r.RequestUri.Equals(new Uri(BaseAddress + uri))).ToArray(); + if (!requests.Any()) + { + throw new AssertionFailedException($"expected a request to {uri}, but only got the following requests: {string.Join(", ", actualRequests.Select(r => r.RequestUri.ToString()))}"); + } + return requests; + } + + public void Enqueue(FakeRequestConfiguration fakeRequestConfiguration) + { + requestConfigurations.Enqueue(fakeRequestConfiguration); + } + } +} \ No newline at end of file diff --git a/src/Oocx.ACME.Tests/FakeHttp/FakeRequestConfiguration.cs b/src/Oocx.ACME.Tests/FakeHttp/FakeRequestConfiguration.cs new file mode 100644 index 0000000..fba1f63 --- /dev/null +++ b/src/Oocx.ACME.Tests/FakeHttp/FakeRequestConfiguration.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using System.Net; +using System.Net.Http; +using System.Net.Http.Formatting; + +namespace Oocx.ACME.Tests.FakeHttp +{ + public class FakeRequestConfiguration + { + private readonly FakeHttpMessageHandler fakeHttpMessageHandler; + private static readonly JsonMediaTypeFormatter Formatter = new JsonMediaTypeFormatter(); + + public FakeRequestConfiguration(FakeHttpMessageHandler fakeHttpMessageHandler) + { + this.fakeHttpMessageHandler = fakeHttpMessageHandler; + fakeHttpMessageHandler.Enqueue(this); + } + + public string Uri { get; set; } + + public ObjectContent Content { get; set; } + + public Dictionary Headers { get; set; } = new Dictionary(); + + public HttpStatusCode StatusCode { get; set; } = HttpStatusCode.OK; + + public FakeRequestConfiguration Returns(T content, string contentType = "application/json") + { + Content = new ObjectContent(content, Formatter); + Content.Headers.ContentType.MediaType = contentType; + return this; + } + + public FakeRequestConfiguration HasStatusCode(HttpStatusCode statusCode) + { + StatusCode = statusCode; + return this; + } + + public FakeRequestConfiguration WithHeader(string key, string value) + { + Headers[key] = value; + return this; + } + + public FakeRequestConfiguration WithNonce(string value) + { + Headers["Replay-Nonce"] = value; + return this; + } + + public FakeRequestConfiguration RequestTo(string uri) + { + return fakeHttpMessageHandler.RequestTo(uri); + } + + public HttpResponseMessage GetResponseMessage() + { + var response = new HttpResponseMessage(StatusCode) { Content = Content}; + foreach (var header in Headers) + { + response.Headers.Add(header.Key, header.Value); + } + return response; + } + + public HttpClient GetHttpClient() + { + var client = new HttpClient(fakeHttpMessageHandler) { BaseAddress = new Uri(fakeHttpMessageHandler.BaseAddress, UriKind.Absolute) }; + return client; + } + } +} \ No newline at end of file diff --git a/src/Oocx.ACME.Tests/FakeHttp/HttpRequestMessageAssertions.cs b/src/Oocx.ACME.Tests/FakeHttp/HttpRequestMessageAssertions.cs new file mode 100644 index 0000000..a7a3596 --- /dev/null +++ b/src/Oocx.ACME.Tests/FakeHttp/HttpRequestMessageAssertions.cs @@ -0,0 +1,48 @@ +using System; +using System.Net.Http; +using System.Text; +using FluentAssertions; +using Newtonsoft.Json; +using Oocx.ACME.Jose; +using Oocx.Asn1PKCS.Asn1BaseTypes; + +namespace Oocx.ACME.Tests.FakeHttp +{ + public static class HttpRequestMessageAssertions + { + public static HttpRequestMessage HasContent(this HttpRequestMessage request, Action contentAssertion) + { + contentAssertion(request.Content); + return request; + } + + public static HttpRequestMessage HasContent(this HttpRequestMessage request, Action contentAssertion) + { + contentAssertion(request.Content.ReadAsAsync().Result); + return request; + } + + public static HttpRequestMessage HasJwsPayload(this HttpRequestMessage request, Action contentAssertion) + { + var message = request.Content.ReadAsAsync().Result; + var contentJson = Encoding.UTF8.GetString(message.Payload.Base64UrlDecode()); + var content = JsonConvert.DeserializeObject(contentJson); + + contentAssertion(content); + return request; + } + + public static HttpRequestMessage HasHeader(this HttpRequestMessage request, string headerName, string headerValue) + { + request.Headers.Should().Contain(headerName); + request.Headers.GetValues(headerName).Should().Contain(headerValue); + return request; + } + + public static HttpRequestMessage HasMethod(this HttpRequestMessage request, HttpMethod method) + { + request.Method.Should().Be(method); + return request; + } + } +} \ No newline at end of file diff --git a/src/Oocx.ACME.Tests/FakeHttp/PreventDisposeContentWrapper.cs b/src/Oocx.ACME.Tests/FakeHttp/PreventDisposeContentWrapper.cs new file mode 100644 index 0000000..9ccdb1e --- /dev/null +++ b/src/Oocx.ACME.Tests/FakeHttp/PreventDisposeContentWrapper.cs @@ -0,0 +1,51 @@ +using System; +using System.IO; +using System.Net; +using System.Net.Http; +using System.Threading.Tasks; + +namespace Oocx.ACME.Tests.FakeHttp +{ + public class PreventDisposeContentWrapper : HttpContent + { + public byte[] Bytes { get; } + public Type ContentType { get; } + + private PreventDisposeContentWrapper(byte[] bytes, Type contentType) + { + Bytes = bytes; + ContentType = contentType; + } + + public static async Task CreateWrapperAsync(HttpContent wrappedContent) + { + if (wrappedContent == null) + { + return new PreventDisposeContentWrapper(new byte[0], null); + } + var bytes = await wrappedContent.ReadAsByteArrayAsync(); + var wrapper = new PreventDisposeContentWrapper(bytes, wrappedContent.GetType()); + foreach (var header in wrappedContent.Headers) + { + wrapper.Headers.Add(header.Key, header.Value); + } + return wrapper; + } + + protected override async Task SerializeToStreamAsync(Stream stream, TransportContext context) + { + await stream.WriteAsync(Bytes, 0, Bytes.Length); + } + + protected override bool TryComputeLength(out long length) + { + length = Bytes.Length; + return true; + } + + protected override void Dispose(bool disposing) + { + + } + } +} \ No newline at end of file diff --git a/src/Oocx.ACME.Tests/project.json b/src/Oocx.ACME.Tests/project.json index ccf357a..f27ba73 100644 --- a/src/Oocx.ACME.Tests/project.json +++ b/src/Oocx.ACME.Tests/project.json @@ -10,8 +10,7 @@ "xunit": "2.1.0", "xunit.runner.dnx": "2.1.0-rc1-build204", "FluentAssertions": "4.0.1", - "NSubstitute": "1.9.2", - "WorldDomination.HttpClient.Helpers": "3.0.1", + "NSubstitute": "1.9.2", "Newtonsoft.Json": "7.0.1", "Oocx.ACME": "", "System.Runtime": "4.0.21-beta-23409", diff --git a/src/Oocx.ACME.Tests/project.lock.json b/src/Oocx.ACME.Tests/project.lock.json index d2c31ec..d8aa201 100644 --- a/src/Oocx.ACME.Tests/project.lock.json +++ b/src/Oocx.ACME.Tests/project.lock.json @@ -33,21 +33,6 @@ "lib/net45/System.Net.Http.Formatting.dll": {} } }, - "Microsoft.Bcl/1.1.10": { - "type": "package", - "dependencies": { - "Microsoft.Bcl.Build": "1.0.14" - }, - "compile": { - "lib/net45/_._": {} - }, - "runtime": { - "lib/net45/_._": {} - } - }, - "Microsoft.Bcl.Build/1.0.14": { - "type": "package" - }, "Microsoft.Dnx.Compilation.Abstractions/1.0.0-rc1-final": { "type": "package", "dependencies": { @@ -169,25 +154,6 @@ "lib/net451/Microsoft.Extensions.PlatformAbstractions.dll": {} } }, - "Microsoft.Net.Http/2.2.29": { - "type": "package", - "dependencies": { - "Microsoft.Bcl": "1.1.10", - "Microsoft.Bcl.Build": "1.0.14" - }, - "frameworkAssemblies": [ - "System.Net.Http", - "System.Net.Http.WebRequest" - ], - "compile": { - "lib/net45/System.Net.Http.Extensions.dll": {}, - "lib/net45/System.Net.Http.Primitives.dll": {} - }, - "runtime": { - "lib/net45/System.Net.Http.Extensions.dll": {}, - "lib/net45/System.Net.Http.Primitives.dll": {} - } - }, "Newtonsoft.Json/7.0.1": { "type": "package", "compile": { @@ -276,18 +242,6 @@ "lib/net46/_._": {} } }, - "WorldDomination.HttpClient.Helpers/3.0.1": { - "type": "package", - "dependencies": { - "Microsoft.Net.Http": "[2.2.29, 3.0.0)" - }, - "compile": { - "lib/net45/WorldDomination.HttpClient.Helpers.dll": {} - }, - "runtime": { - "lib/net45/WorldDomination.HttpClient.Helpers.dll": {} - } - }, "xunit/2.1.0": { "type": "package", "dependencies": { @@ -429,21 +383,6 @@ "lib/net45/System.Net.Http.Formatting.dll": {} } }, - "Microsoft.Bcl/1.1.10": { - "type": "package", - "dependencies": { - "Microsoft.Bcl.Build": "1.0.14" - }, - "compile": { - "lib/net45/_._": {} - }, - "runtime": { - "lib/net45/_._": {} - } - }, - "Microsoft.Bcl.Build/1.0.14": { - "type": "package" - }, "Microsoft.Dnx.Compilation.Abstractions/1.0.0-rc1-final": { "type": "package", "dependencies": { @@ -565,25 +504,6 @@ "lib/net451/Microsoft.Extensions.PlatformAbstractions.dll": {} } }, - "Microsoft.Net.Http/2.2.29": { - "type": "package", - "dependencies": { - "Microsoft.Bcl": "1.1.10", - "Microsoft.Bcl.Build": "1.0.14" - }, - "frameworkAssemblies": [ - "System.Net.Http", - "System.Net.Http.WebRequest" - ], - "compile": { - "lib/net45/System.Net.Http.Extensions.dll": {}, - "lib/net45/System.Net.Http.Primitives.dll": {} - }, - "runtime": { - "lib/net45/System.Net.Http.Extensions.dll": {}, - "lib/net45/System.Net.Http.Primitives.dll": {} - } - }, "Newtonsoft.Json/7.0.1": { "type": "package", "compile": { @@ -684,18 +604,6 @@ "lib/net46/_._": {} } }, - "WorldDomination.HttpClient.Helpers/3.0.1": { - "type": "package", - "dependencies": { - "Microsoft.Net.Http": "[2.2.29, 3.0.0)" - }, - "compile": { - "lib/net45/WorldDomination.HttpClient.Helpers.dll": {} - }, - "runtime": { - "lib/net45/WorldDomination.HttpClient.Helpers.dll": {} - } - }, "xunit/2.1.0": { "type": "package", "dependencies": { @@ -837,21 +745,6 @@ "lib/net45/System.Net.Http.Formatting.dll": {} } }, - "Microsoft.Bcl/1.1.10": { - "type": "package", - "dependencies": { - "Microsoft.Bcl.Build": "1.0.14" - }, - "compile": { - "lib/net45/_._": {} - }, - "runtime": { - "lib/net45/_._": {} - } - }, - "Microsoft.Bcl.Build/1.0.14": { - "type": "package" - }, "Microsoft.Dnx.Compilation.Abstractions/1.0.0-rc1-final": { "type": "package", "dependencies": { @@ -973,25 +866,6 @@ "lib/net451/Microsoft.Extensions.PlatformAbstractions.dll": {} } }, - "Microsoft.Net.Http/2.2.29": { - "type": "package", - "dependencies": { - "Microsoft.Bcl": "1.1.10", - "Microsoft.Bcl.Build": "1.0.14" - }, - "frameworkAssemblies": [ - "System.Net.Http", - "System.Net.Http.WebRequest" - ], - "compile": { - "lib/net45/System.Net.Http.Extensions.dll": {}, - "lib/net45/System.Net.Http.Primitives.dll": {} - }, - "runtime": { - "lib/net45/System.Net.Http.Extensions.dll": {}, - "lib/net45/System.Net.Http.Primitives.dll": {} - } - }, "Newtonsoft.Json/7.0.1": { "type": "package", "compile": { @@ -1092,18 +966,6 @@ "lib/net46/_._": {} } }, - "WorldDomination.HttpClient.Helpers/3.0.1": { - "type": "package", - "dependencies": { - "Microsoft.Net.Http": "[2.2.29, 3.0.0)" - }, - "compile": { - "lib/net45/WorldDomination.HttpClient.Helpers.dll": {} - }, - "runtime": { - "lib/net45/WorldDomination.HttpClient.Helpers.dll": {} - } - }, "xunit/2.1.0": { "type": "package", "dependencies": { @@ -1329,115 +1191,6 @@ "Microsoft.AspNet.WebApi.Client.nuspec" ] }, - "Microsoft.Bcl/1.1.10": { - "type": "package", - "sha512": "+tTqoh/M1pyL8El3qLy30EcwnAtyvFoDZJtdG9Cbg/WdFbh4N8kyrq198XHuEL7lnJbeD0DRO8jcX5IIOh05cQ==", - "files": [ - "lib/monoandroid/_._", - "lib/monotouch/_._", - "lib/net40/ensureRedirect.xml", - "lib/net40/System.IO.dll", - "lib/net40/System.IO.xml", - "lib/net40/System.Runtime.dll", - "lib/net40/System.Runtime.xml", - "lib/net40/System.Threading.Tasks.dll", - "lib/net40/System.Threading.Tasks.xml", - "lib/net45/_._", - "lib/portable-net40+sl4+win8/ensureRedirect.xml", - "lib/portable-net40+sl4+win8/System.IO.dll", - "lib/portable-net40+sl4+win8/System.IO.xml", - "lib/portable-net40+sl4+win8/System.Runtime.dll", - "lib/portable-net40+sl4+win8/System.Runtime.xml", - "lib/portable-net40+sl4+win8/System.Threading.Tasks.dll", - "lib/portable-net40+sl4+win8/System.Threading.Tasks.xml", - "lib/portable-net40+sl4+win8+wp71+wpa81/ensureRedirect.xml", - "lib/portable-net40+sl4+win8+wp71+wpa81/System.IO.dll", - "lib/portable-net40+sl4+win8+wp71+wpa81/System.IO.xml", - "lib/portable-net40+sl4+win8+wp71+wpa81/System.Runtime.dll", - "lib/portable-net40+sl4+win8+wp71+wpa81/System.Runtime.xml", - "lib/portable-net40+sl4+win8+wp71+wpa81/System.Threading.Tasks.dll", - "lib/portable-net40+sl4+win8+wp71+wpa81/System.Threading.Tasks.xml", - "lib/portable-net40+sl4+win8+wp8+wpa81/ensureRedirect.xml", - "lib/portable-net40+sl4+win8+wp8+wpa81/System.IO.dll", - "lib/portable-net40+sl4+win8+wp8+wpa81/System.IO.xml", - "lib/portable-net40+sl4+win8+wp8+wpa81/System.Runtime.dll", - "lib/portable-net40+sl4+win8+wp8+wpa81/System.Runtime.xml", - "lib/portable-net40+sl4+win8+wp8+wpa81/System.Threading.Tasks.dll", - "lib/portable-net40+sl4+win8+wp8+wpa81/System.Threading.Tasks.xml", - "lib/portable-net40+sl5+win8+wp8+wpa81/ensureRedirect.xml", - "lib/portable-net40+sl5+win8+wp8+wpa81/System.IO.dll", - "lib/portable-net40+sl5+win8+wp8+wpa81/System.IO.xml", - "lib/portable-net40+sl5+win8+wp8+wpa81/System.Runtime.dll", - "lib/portable-net40+sl5+win8+wp8+wpa81/System.Runtime.xml", - "lib/portable-net40+sl5+win8+wp8+wpa81/System.Threading.Tasks.dll", - "lib/portable-net40+sl5+win8+wp8+wpa81/System.Threading.Tasks.xml", - "lib/portable-net40+win8/ensureRedirect.xml", - "lib/portable-net40+win8/System.IO.dll", - "lib/portable-net40+win8/System.IO.xml", - "lib/portable-net40+win8/System.Runtime.dll", - "lib/portable-net40+win8/System.Runtime.xml", - "lib/portable-net40+win8/System.Threading.Tasks.dll", - "lib/portable-net40+win8/System.Threading.Tasks.xml", - "lib/portable-net40+win8+wp8+wpa81/ensureRedirect.xml", - "lib/portable-net40+win8+wp8+wpa81/System.IO.dll", - "lib/portable-net40+win8+wp8+wpa81/System.IO.xml", - "lib/portable-net40+win8+wp8+wpa81/System.Runtime.dll", - "lib/portable-net40+win8+wp8+wpa81/System.Runtime.xml", - "lib/portable-net40+win8+wp8+wpa81/System.Threading.Tasks.dll", - "lib/portable-net40+win8+wp8+wpa81/System.Threading.Tasks.xml", - "lib/portable-net45+win8+wp8+wpa81/_._", - "lib/portable-net45+win8+wpa81/_._", - "lib/portable-net451+win81/_._", - "lib/portable-net451+win81+wpa81/_._", - "lib/portable-win81+wp81+wpa81/_._", - "lib/sl4/System.IO.dll", - "lib/sl4/System.IO.xml", - "lib/sl4/System.Runtime.dll", - "lib/sl4/System.Runtime.xml", - "lib/sl4/System.Threading.Tasks.dll", - "lib/sl4/System.Threading.Tasks.xml", - "lib/sl4-windowsphone71/ensureRedirect.xml", - "lib/sl4-windowsphone71/System.IO.dll", - "lib/sl4-windowsphone71/System.IO.xml", - "lib/sl4-windowsphone71/System.Runtime.dll", - "lib/sl4-windowsphone71/System.Runtime.xml", - "lib/sl4-windowsphone71/System.Threading.Tasks.dll", - "lib/sl4-windowsphone71/System.Threading.Tasks.xml", - "lib/sl5/System.IO.dll", - "lib/sl5/System.IO.xml", - "lib/sl5/System.Runtime.dll", - "lib/sl5/System.Runtime.xml", - "lib/sl5/System.Threading.Tasks.dll", - "lib/sl5/System.Threading.Tasks.xml", - "lib/win8/_._", - "lib/wp8/_._", - "lib/wpa81/_._", - "lib/Xamarin.iOS10/_._", - "License-Stable.rtf", - "Microsoft.Bcl.1.1.10.nupkg", - "Microsoft.Bcl.1.1.10.nupkg.sha512", - "Microsoft.Bcl.nuspec" - ] - }, - "Microsoft.Bcl.Build/1.0.14": { - "type": "package", - "sha512": "cDLKSvNvRa519hplsbSoYqO69TjdDIhfjtKUM0g20/nVROoWsGav9KCI9HtnGjLmdV1+TcUUDhbotcllibjPEA==", - "files": [ - "content/net40/_._", - "content/netcore45/_._", - "content/portable-net40+win8+sl4+wp71+wpa81/_._", - "content/sl4/_._", - "content/sl4-windowsphone71/_._", - "License-Stable.rtf", - "Microsoft.Bcl.Build.1.0.14.nupkg", - "Microsoft.Bcl.Build.1.0.14.nupkg.sha512", - "Microsoft.Bcl.Build.nuspec", - "tools/Install.ps1", - "tools/Microsoft.Bcl.Build.targets", - "tools/Microsoft.Bcl.Build.Tasks.dll", - "tools/Uninstall.ps1" - ] - }, "Microsoft.Dnx.Compilation.Abstractions/1.0.0-rc1-final": { "type": "package", "serviceable": true, @@ -1543,74 +1296,6 @@ "Microsoft.Extensions.PlatformAbstractions.nuspec" ] }, - "Microsoft.Net.Http/2.2.29": { - "type": "package", - "serviceable": true, - "sha512": "fc4CPEewJ30Xgal+fSq1lYIBt582A7eKlAL7O4HXiYAiTp2VTnA4osSvk7T2n8aS4xTCPVJusQk3yKLT0XSpkg==", - "files": [ - "lib/monoandroid/System.Net.Http.Extensions.dll", - "lib/monoandroid/System.Net.Http.Extensions.XML", - "lib/monoandroid/System.Net.Http.Primitives.dll", - "lib/monoandroid/System.Net.Http.Primitives.xml", - "lib/monotouch/System.Net.Http.Extensions.dll", - "lib/monotouch/System.Net.Http.Extensions.XML", - "lib/monotouch/System.Net.Http.Primitives.dll", - "lib/monotouch/System.Net.Http.Primitives.xml", - "lib/net40/ensureRedirect.xml", - "lib/net40/System.Net.Http.dll", - "lib/net40/System.Net.Http.Extensions.dll", - "lib/net40/System.Net.Http.Extensions.XML", - "lib/net40/System.Net.Http.Primitives.dll", - "lib/net40/System.Net.Http.Primitives.xml", - "lib/net40/System.Net.Http.WebRequest.dll", - "lib/net40/System.Net.Http.WebRequest.xml", - "lib/net40/System.Net.Http.xml", - "lib/net45/ensureRedirect.xml", - "lib/net45/System.Net.Http.Extensions.dll", - "lib/net45/System.Net.Http.Extensions.XML", - "lib/net45/System.Net.Http.Primitives.dll", - "lib/net45/System.Net.Http.Primitives.xml", - "lib/portable-net40+sl4+win8+wp71+wpa81/ensureRedirect.xml", - "lib/portable-net40+sl4+win8+wp71+wpa81/System.Net.Http.dll", - "lib/portable-net40+sl4+win8+wp71+wpa81/System.Net.Http.Extensions.dll", - "lib/portable-net40+sl4+win8+wp71+wpa81/System.Net.Http.Extensions.XML", - "lib/portable-net40+sl4+win8+wp71+wpa81/System.Net.Http.Primitives.dll", - "lib/portable-net40+sl4+win8+wp71+wpa81/System.Net.Http.Primitives.XML", - "lib/portable-net40+sl4+win8+wp71+wpa81/System.Net.Http.xml", - "lib/portable-net45+win8/ensureRedirect.xml", - "lib/portable-net45+win8/System.Net.Http.Extensions.dll", - "lib/portable-net45+win8/System.Net.Http.Extensions.XML", - "lib/portable-net45+win8/System.Net.Http.Primitives.dll", - "lib/portable-net45+win8/System.Net.Http.Primitives.xml", - "lib/portable-net45+win8+wpa81/ensureRedirect.xml", - "lib/portable-net45+win8+wpa81/System.Net.Http.Extensions.dll", - "lib/portable-net45+win8+wpa81/System.Net.Http.Extensions.XML", - "lib/portable-net45+win8+wpa81/System.Net.Http.Primitives.dll", - "lib/portable-net45+win8+wpa81/System.Net.Http.Primitives.xml", - "lib/sl4-windowsphone71/System.Net.Http.dll", - "lib/sl4-windowsphone71/System.Net.Http.Extensions.dll", - "lib/sl4-windowsphone71/System.Net.Http.Extensions.XML", - "lib/sl4-windowsphone71/System.Net.Http.Primitives.dll", - "lib/sl4-windowsphone71/System.Net.Http.Primitives.XML", - "lib/sl4-windowsphone71/System.Net.Http.xml", - "lib/win8/System.Net.Http.Extensions.dll", - "lib/win8/System.Net.Http.Extensions.XML", - "lib/win8/System.Net.Http.Primitives.dll", - "lib/win8/System.Net.Http.Primitives.xml", - "lib/wpa81/System.Net.Http.Extensions.dll", - "lib/wpa81/System.Net.Http.Extensions.XML", - "lib/wpa81/System.Net.Http.Primitives.dll", - "lib/wpa81/System.Net.Http.Primitives.xml", - "lib/Xamarin.iOS10/System.Net.Http.Extensions.dll", - "lib/Xamarin.iOS10/System.Net.Http.Extensions.XML", - "lib/Xamarin.iOS10/System.Net.Http.Primitives.dll", - "lib/Xamarin.iOS10/System.Net.Http.Primitives.xml", - "License-Stable.rtf", - "Microsoft.Net.Http.2.2.29.nupkg", - "Microsoft.Net.Http.2.2.29.nupkg.sha512", - "Microsoft.Net.Http.nuspec" - ] - }, "Newtonsoft.Json/7.0.1": { "type": "package", "sha512": "q3V4KLetMLnt1gpAVWgtXnHjKs0UG/RalBc29u2ZKxd5t5Ze4JBL5WiiYIklJyK/5CRiIiNwigVQUo0FgbsuWA==", @@ -1872,16 +1557,6 @@ "System.Threading.nuspec" ] }, - "WorldDomination.HttpClient.Helpers/3.0.1": { - "type": "package", - "sha512": "rVWmcdEYJL6diRGWfmQ5RZTKaqRoBk7x+dtnOuwBDlr0IZQosGSc02JQMNn15D/xBJ0V7XO88oVLiYcapk5fpw==", - "files": [ - "lib/net45/WorldDomination.HttpClient.Helpers.dll", - "WorldDomination.HttpClient.Helpers.3.0.1.nupkg", - "WorldDomination.HttpClient.Helpers.3.0.1.nupkg.sha512", - "WorldDomination.HttpClient.Helpers.nuspec" - ] - }, "xunit/2.1.0": { "type": "package", "sha512": "u/7VQSOSXa7kSG4iK6Lcn7RqKZQ3hk7cnyMNVMpXHSP0RI5VQEtc44hvkG3LyWOVsx1dhUDD3rPAHAxyOUDQJw==", @@ -2052,7 +1727,6 @@ "xunit.runner.dnx >= 2.1.0-rc1-build204", "FluentAssertions >= 4.0.1", "NSubstitute >= 1.9.2", - "WorldDomination.HttpClient.Helpers >= 3.0.1", "Newtonsoft.Json >= 7.0.1", "Oocx.ACME ", "System.Runtime >= 4.0.21-beta-23409", diff --git a/src/Oocx.ACME/Client/AcmeClient.cs b/src/Oocx.ACME/Client/AcmeClient.cs index 9556438..0233e03 100644 --- a/src/Oocx.ACME/Client/AcmeClient.cs +++ b/src/Oocx.ACME/Client/AcmeClient.cs @@ -53,7 +53,7 @@ private void RememberNonce(HttpResponseMessage response) Verbose($"nonce from server is {nonce}"); } - public async Task RegisterAsync(bool acceptTermsOfService) + public async Task RegisterAsync(string termsOfServiceUri, string[] contact) { await EnsureDirectory(); @@ -61,8 +61,8 @@ public async Task RegisterAsync(bool acceptTermsOfService) var request = new NewRegistrationRequest() { - Contact = new[] { "mailto:mathias@raacke.info" }, - Agreement = acceptTermsOfService ? "https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf" : null + Contact = contact, + Agreement = termsOfServiceUri }; try @@ -88,7 +88,7 @@ public async Task EnsureDirectory() } } - public async Task UpdateRegistrationAsync(string registrationUri, string agreementUri) + public async Task UpdateRegistrationAsync(string registrationUri, string agreementUri, string[] contact) { await EnsureDirectory(); @@ -96,8 +96,8 @@ public async Task UpdateRegistrationAsync(string registrat var registration = new UpdateRegistrationRequest() { - Contact = new[] { "mailto:mathias@raacke.info" }, - Agreement = agreementUri ?? "https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf" + Contact = contact, + Agreement = agreementUri }; return await PostAsync(new Uri(registrationUri), registration); diff --git a/src/Oocx.ACME/Client/IAcmeClient.cs b/src/Oocx.ACME/Client/IAcmeClient.cs index e18551e..eb0b99a 100644 --- a/src/Oocx.ACME/Client/IAcmeClient.cs +++ b/src/Oocx.ACME/Client/IAcmeClient.cs @@ -7,9 +7,9 @@ public interface IAcmeClient { string GetKeyAuthorization(string token); Task DiscoverAsync(); - Task RegisterAsync(bool acceptTermsOfService); + Task RegisterAsync(string termsOfServiceUri, string[] contact); Task EnsureDirectory(); - Task UpdateRegistrationAsync(string registrationUri, string agreementUri); + Task UpdateRegistrationAsync(string registrationUri, string agreementUri, string[] contact); Task NewDnsAuthorizationAsync(string dnsName); Task CompleteChallengeAsync(Challenge challenge); Task NewCertificateRequestAsync(byte[] csr);