diff --git a/src/Certes/Acme/AcmeDirectory.cs b/src/Certes/Acme/AcmeDirectory.cs new file mode 100644 index 00000000..49238396 --- /dev/null +++ b/src/Certes/Acme/AcmeDirectory.cs @@ -0,0 +1,108 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; + +namespace Certes.Acme +{ + /// + /// Represents the ACME directory. + /// + public class AcmeDirectory + { + /// + /// Gets or sets the new nonce endpoint. + /// + /// + /// The new nonce endpoint. + /// + [JsonProperty("new-nonce")] + public Uri NewNonce { get; set; } + + /// + /// Gets or sets the new certificate endpoint. + /// + /// + /// The new certificate endpoint. + /// + [JsonProperty("new-cert")] + public Uri NewCert { get; set; } + + /// + /// Gets or sets the new authorization endpoint. + /// + /// + /// The new authorization endpoint. + /// + [JsonProperty("new-authz")] + public Uri NewAuthz { get; set; } + + /// + /// Gets or sets the revoke cert. + /// + /// + /// The revoke cert. + /// + [JsonProperty("revoke-cert")] + public Uri RevokeCert { get; set; } + + /// + /// Gets or sets the key change endpoint. + /// + /// + /// The key change endpoint. + /// + [JsonProperty("key-change")] + public Uri KeyChange { get; set; } + + /// + /// Gets or sets the new registration endpoint. + /// + /// + /// The new registration endpoint. + /// + [JsonProperty("new-reg")] + public Uri NewReg { get; set; } + + /// + /// Gets or sets the metadata. + /// + /// + /// The metadata. + /// + [JsonProperty("meta")] + public AcmeDirectoryMeta Meta { get; set; } + + /// + /// Represents the metadata for ACME directory. + /// + public class AcmeDirectoryMeta + { + /// + /// Gets or sets the terms of service. + /// + /// + /// The terms of service. + /// + [JsonProperty("terms-of-service")] + public Uri TermsOfService { get; set; } + + /// + /// Gets or sets the website. + /// + /// + /// The website. + /// + [JsonProperty("website")] + public Uri Website { get; set; } + + /// + /// Gets or sets the caa identities. + /// + /// + /// The caa identities. + /// + [JsonProperty("caa-identities")] + public IList CaaIdentities { get; set; } + } + } +} diff --git a/src/Certes/Acme/AcmeHttpHandler.cs b/src/Certes/Acme/AcmeHttpHandler.cs index e09fe5bb..58130c33 100644 --- a/src/Certes/Acme/AcmeHttpHandler.cs +++ b/src/Certes/Acme/AcmeHttpHandler.cs @@ -8,8 +8,6 @@ using System.Text; using System.Threading.Tasks; -using AcmeDirectory = System.Collections.Generic.Dictionary; - namespace Certes.Acme { /// @@ -61,7 +59,19 @@ public AcmeHttpHandler(Uri serverUri, HttpMessageHandler httpMessageHandler = nu public async Task GetResourceUri(string resourceType) { await FetchDirectory(false); - return new Uri(this.directory[resourceType] as String); + var resourceUri = + ResourceTypes.NewRegistration == resourceType ? this.directory.NewReg : + ResourceTypes.NewAuthorization == resourceType ? this.directory.NewAuthz : + ResourceTypes.NewCertificate == resourceType ? this.directory.NewCert : + ResourceTypes.RevokeCertificate == resourceType ? this.directory.RevokeCert : + null; + + if (resourceUri == null) + { + throw new Exception($"Unsupported resource type '{resourceType}'."); + } + + return resourceUri; } /// diff --git a/src/Certes/Acme/AuthorizationIdentifier.cs b/src/Certes/Acme/AuthorizationIdentifier.cs index f35c6984..3f3825de 100644 --- a/src/Certes/Acme/AuthorizationIdentifier.cs +++ b/src/Certes/Acme/AuthorizationIdentifier.cs @@ -1,9 +1,11 @@ -namespace Certes.Acme +using System; + +namespace Certes.Acme { /// /// Represents the identifier for ACME Authorization. /// - public class AuthorizationIdentifier + public class AuthorizationIdentifier : IEquatable { /// /// Gets or sets the type. @@ -42,7 +44,18 @@ public override int GetHashCode() /// public override bool Equals(object obj) { - var other = obj as AuthorizationIdentifier; + return this.Equals(obj as AuthorizationIdentifier); + } + + /// + /// Determines whether the specified , is equal to this instance. + /// + /// The to compare with this instance. + /// + /// true if the specified is equal to this instance; otherwise, false. + /// + public bool Equals(AuthorizationIdentifier other) + { return other?.Type == this.Type && other?.Value == this.Value; } } diff --git a/test/Certes.Tests.Web/Certes.Tests.Web.csproj b/test/Certes.Tests.Web/Certes.Tests.Web.csproj index 04adc696..ca763871 100644 --- a/test/Certes.Tests.Web/Certes.Tests.Web.csproj +++ b/test/Certes.Tests.Web/Certes.Tests.Web.csproj @@ -2,18 +2,20 @@ netcoreapp1.1 - 1.1.1 false false false - + + + + - + diff --git a/test/Certes.Tests/AcmeClientTests.cs b/test/Certes.Tests/AcmeClientTests.cs index 1942cc80..a974d225 100644 --- a/test/Certes.Tests/AcmeClientTests.cs +++ b/test/Certes.Tests/AcmeClientTests.cs @@ -1,18 +1,16 @@ using Certes.Acme; +using Certes.Json; using Certes.Jws; -using Certes.Pkcs; using Moq; using Moq.Protected; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; -using System.Collections.Generic; using System.Net; using System.Net.Http; using System.Text; using System.Threading; using System.Threading.Tasks; -using Certes.Json; using Xunit; namespace Certes.Tests @@ -24,20 +22,17 @@ public class AcmeClientTests private const string NonceFormat = "nonce-{0}"; private readonly Uri server = new Uri("http://example.com/dir"); private readonly Uri tos = new Uri("http://example.com/tos"); - private readonly Dictionary legacyDictData = new Dictionary - { - { "new-authz", new Uri("http://example.com/new-authz") }, - { "new-cert", new Uri("http://example.com/new-cert") }, - { "new-reg", new Uri("http://example.com/new-reg") }, - { "revoke-cert", new Uri("http://example.com/revoke-cert") }, - }; - private readonly Dictionary dictData = new Dictionary + + private readonly AcmeDirectory acmeDict = new AcmeDirectory { - { "meta", new Dictionary { { "terms-of-service", "http://example.com/tos.pdf" } } }, - { "new-authz", "http://example.com/new-authz" }, - { "new-cert", "http://example.com/new-cert" }, - { "new-reg", "http://example.com/new-reg" }, - { "revoke-cert", "http://example.com/revoke-cert" }, + Meta = new AcmeDirectory.AcmeDirectoryMeta + { + TermsOfService = new Uri("http://example.com/tos.pdf") + }, + NewAuthz = new Uri("http://example.com/new-authz"), + NewCert = new Uri("http://example.com/new-cert"), + NewReg = new Uri("http://example.com/new-reg"), + RevokeCert = new Uri("http://example.com/revoke-cert") }; private int nonce = 0; @@ -49,7 +44,7 @@ public async Task CanCreateRegistration() var regLocation = new Uri("http://example.com/reg/1"); var mock = MockHttp(async req => { - if (req.Method == HttpMethod.Post && req.RequestUri == new Uri(dictData["new-reg"] as String)) + if (req.Method == HttpMethod.Post && req.RequestUri == acmeDict.NewReg) { var payload = await ParsePayload(req); Assert.Equal(ResourceTypes.NewRegistration, payload.Resource); @@ -183,7 +178,7 @@ private Mock MockHttp(Func