Ejemplo n.º 1
0
 public async Task ShouldFailWhenCompleteChallengeWithoutAccount()
 {
     using (var client = new AcmeClient(WellKnownServers.LetsEncryptStaging))
     {
         await Assert.ThrowsAsync <InvalidOperationException>(
             () => client.CompleteChallenge(new ChallengeEntity()));
     }
 }
Ejemplo n.º 2
0
 public async Task ShouldFailWhenUpdateRegistrationWithoutAccount()
 {
     using (var client = new AcmeClient(WellKnownServers.LetsEncryptStaging))
     {
         await Assert.ThrowsAsync <InvalidOperationException>(
             () => client.UpdateRegistration(new AcmeAccount()));
     }
 }
Ejemplo n.º 3
0
        public async Task CanUpdateRegistration()
        {
            var accountKey = await Helper.LoadkeyV1();

            var regLocation = new Uri("http://example.com/reg/1");
            var mock        = MockHttp(async req =>
            {
                if (req.Method == HttpMethod.Post && req.RequestUri == regLocation)
                {
                    var payload = await ParsePayload <RegistrationEntity>(req);
                    Assert.Equal(ResourceTypes.Registration, payload.Resource);
                    Assert.Equal(1, payload.Contact?.Count);
                    Assert.Equal($"another-{email}", payload.Contact[0]);
                    Assert.NotNull(payload.Agreement);

                    var respJson = new
                    {
                        contact   = payload.Contact,
                        agreement = payload.Agreement,
                        resource  = ResourceTypes.Registration
                    };

                    var resp = CreateResponse(respJson, HttpStatusCode.Created, regLocation);
                    resp.Headers.Add("Link", $"<{tos}>; rel=\"terms-of-service\"");
                    return(resp);
                }

                return(null);
            });

            using (var http = new HttpClient(mock.Object))
                using (var handler = new AcmeHttpHandler(server, http))
                {
                    using (var client = new AcmeClient(handler))
                    {
                        client.Use(accountKey.Export());

                        var account = new AcmeAccount
                        {
                            Location = regLocation,
                            Data     = new RegistrationEntity
                            {
                                Resource  = ResourceTypes.Registration,
                                Contact   = new[] { $"another-{email}" },
                                Agreement = tos
                            }
                        };

                        var result = await client.UpdateRegistration(account);

                        Assert.Equal(ResourceTypes.Registration, result.Data.Resource);
                        Assert.Equal(tos, account.Data.Agreement);
                        Assert.Equal(regLocation, account.Location);
                    }

                    mock.As <IDisposable>().Verify(x => x.Dispose(), Times.Never());
                }
        }
        public async Task CanDeleteRegistration()
        {
            using (var client = new AcmeClient(WellKnownServers.LetsEncryptStaging))
            {
                var reg = await client.NewRegistraton();

                await client.DeleteRegistration(reg);
            }
        }
Ejemplo n.º 5
0
        public async Task CanDeleteRegistration()
        {
            var accountKey = await Helper.LoadkeyV1();

            var regLocation = new Uri("http://example.com/reg/1");
            var mock        = MockHttp(async req =>
            {
                if (req.Method == HttpMethod.Post && req.RequestUri == regLocation)
                {
                    var payload = await ParsePayload <RegistrationEntity>(req);
                    Assert.Equal(ResourceTypes.Registration, payload.Resource);
                    Assert.True(payload.Delete);

                    var resp = CreateResponse(null, HttpStatusCode.OK, regLocation);
                    resp.Headers.Add("Link", $"<{tos}>; rel=\"terms-of-service\"");
                    return(resp);
                }

                return(null);
            });

            using (var http = new HttpClient(mock.Object))
                using (var handler = new AcmeHttpHandler(server, http))
                {
                    using (var client = new AcmeClient(handler))
                    {
                        var account = new AcmeAccount
                        {
                            Location = regLocation,
                            Data     = new RegistrationEntity
                            {
                                Resource  = ResourceTypes.Registration,
                                Contact   = new[] { $"another-{email}" },
                                Agreement = tos
                            }
                        };

                        try
                        {
                            await client.DeleteRegistration(account);

                            Assert.False(true);
                        }
                        catch (InvalidOperationException)
                        {
                        }

                        client.Use(accountKey.Export());
                        await client.DeleteRegistration(account);
                    }

                    mock.As <IDisposable>().Verify(x => x.Dispose(), Times.Never());
                }
        }
        public async Task CanChangeKey()
        {
            using (var client = new AcmeClient(WellKnownServers.LetsEncryptStaging))
            {
                var reg = await client.NewRegistraton();

                var newKey = new AccountKey().Export();
                await client.ChangeKey(reg, newKey);

                await client.DeleteRegistration(reg);
            }
        }
Ejemplo n.º 7
0
        public async Task CanHandlerxistingAuthorization()
        {
            var accountKey = await Helper.LoadkeyV1();

            var authzUri = new Uri("http://example.com/new-authz");
            var authzLoc = new Uri("http://example.com/authz/111");
            var mock     = MockHttp(async req =>
            {
                if (req.Method == HttpMethod.Post && req.RequestUri == authzUri)
                {
                    var payload = await ParsePayload <AuthorizationEntity>(req);
                    return(CreateResponse(null, HttpStatusCode.SeeOther, authzLoc));
                }

                if (req.Method == HttpMethod.Get && req.RequestUri == authzLoc)
                {
                    return(CreateResponse(new AuthorizationEntity
                    {
                        Identifier = new AuthorizationIdentifier
                        {
                            Type = AuthorizationIdentifierTypes.Dns,
                            Value = "www.example.com",
                        },
                        Status = EntityStatus.Pending,
                    }, HttpStatusCode.OK, authzLoc));
                }

                return(null);
            });

            using (var http = new HttpClient(mock.Object))
                using (var handler = new AcmeHttpHandler(server, http))
                {
                    using (var client = new AcmeClient(handler))
                    {
                        client.Use(accountKey.Export());

                        var authz = await client.NewAuthorization(new AuthorizationIdentifier
                        {
                            Type  = AuthorizationIdentifierTypes.Dns,
                            Value = "www.example.com"
                        });

                        Assert.NotNull(authz);
                        Assert.Equal(authzLoc, authz.Location);
                    }

                    mock.As <IDisposable>().Verify(x => x.Dispose(), Times.Never());
                }
        }
Ejemplo n.º 8
0
        public void CanCreateWithUri()
        {
            var uri = WellKnownServers.LetsEncryptStaging;

            using (var client = new AcmeClient(uri))
            {
                var type  = typeof(AcmeClient).GetTypeInfo();
                var field = type.GetField("shouldDisposeHander", BindingFlags.NonPublic | BindingFlags.Instance);
                Assert.True((bool)field.GetValue(client));
                Assert.NotNull(client.HttpHandler);

                Assert.Equal(uri, client.HttpHandler.ServerUri);
            }
        }
Ejemplo n.º 9
0
        public static async Task <Uri> GetAcmeUriV1()
        {
            if (stagingServerV1 != null)
            {
                return(stagingServerV1);
            }

            var key = await Helper.LoadkeyV1();

            foreach (var uri in StagingServersV1)
            {
                var httpSucceed = false;
                try
                {
                    await http.Value.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead);

                    httpSucceed = true;
                }
                catch
                {
                }

                if (httpSucceed)
                {
                    using (var client = new AcmeClient(new AcmeHttpHandler(uri, http.Value)))
                    {
                        client.Use(key.Export());

                        try
                        {
                            var account = await client.NewRegistraton();

                            account.Data.Agreement = account.GetTermsOfServiceUri();
                            await client.UpdateRegistration(account);
                        }
                        catch
                        {
                            // account already exists
                        }

                        return(stagingServerV1 = uri);
                    }
                }
            }

            throw new Exception("Staging server unavailable.");
        }
Ejemplo n.º 10
0
        public async Task CanCreateRegistration()
        {
            var accountKey = await Helper.LoadkeyV1();

            var regLocation = new Uri("http://example.com/reg/1");
            var mock        = MockHttp(async req =>
            {
                if (req.Method == HttpMethod.Post && req.RequestUri == acmeDir.NewReg)
                {
                    var payload = await ParsePayload <RegistrationEntity>(req);
                    Assert.Equal(ResourceTypes.NewRegistration, payload.Resource);
                    Assert.Equal(1, payload.Contact?.Count);
                    Assert.Equal(email, payload.Contact[0]);

                    var respJson = new
                    {
                        contact  = payload.Contact,
                        resource = ResourceTypes.Registration
                    };

                    var resp = CreateResponse(respJson, HttpStatusCode.Created, regLocation);
                    resp.Headers.Add("Link", $"<{tos}>; rel=\"terms-of-service\"");
                    return(resp);
                }

                return(null);
            });

            using (var http = new HttpClient(mock.Object))
                using (var handler = new AcmeHttpHandler(server, http))
                {
                    using (var client = new AcmeClient(handler))
                    {
                        client.Use(accountKey.Export());

                        var account = await client.NewRegistraton(email);

                        Assert.Equal(ResourceTypes.Registration, account.Data.Resource);
                        Assert.Null(account.Data.Agreement);
                        Assert.Equal(regLocation, account.Location);
                        Assert.Equal(tos, account.GetTermsOfServiceUri());
                    }

                    mock.Protected().Verify("Dispose", Times.Never(), true);
                }
        }
Ejemplo n.º 11
0
        public async Task CanNewRegistraton()
        {
            var accountKey = await Helper.LoadkeyV1();

            var contacts    = new string[] { "mailto:[email protected]" };
            var regLocation = new Uri("http://example.com/reg/1");
            var mock        = MockHttp(async req =>
            {
                if (req.Method == HttpMethod.Post && req.RequestUri == Helper.MockDirectoryV1.NewReg)
                {
                    var payload = await ParsePayload <RegistrationEntity>(req);
                    Assert.Equal(ResourceTypes.NewRegistration, payload.Resource);
                    Assert.Equal(contacts.Clone(), payload.Contact);

                    var respJson = new
                    {
                        contact   = payload.Contact,
                        agreement = payload.Agreement,
                        resource  = ResourceTypes.Registration
                    };

                    var resp = CreateResponse(respJson, HttpStatusCode.Created, regLocation);
                    resp.Headers.Add("Link", $"<{tos}>; rel=\"terms-of-service\"");
                    return(resp);
                }

                return(null);
            });

            using (var http = new HttpClient(mock.Object))
                using (var handler = new AcmeHttpHandler(server, http))
                {
                    using (var client = new AcmeClient(handler))
                    {
                        client.Use(accountKey.Export());
                        var result = await client.NewRegistraton(contacts);

                        Assert.Equal(ResourceTypes.Registration, result.Data.Resource);
                        Assert.Equal(regLocation, result.Location);
                    }

                    mock.As <IDisposable>().Verify(x => x.Dispose(), Times.Never());
                }
        }
Ejemplo n.º 12
0
        public async Task CanIssueSan()
        {
            var accountKey = await Helper.LoadkeyV1();

            var csr = new CertificationRequestBuilder();

            csr.AddName("C=CA, ST=Ontario, L=Toronto, O=Certes, OU=Dev, CN=www.certes-ci.dymetis.com");
            csr.SubjectAlternativeNames.Add("mail.certes-ci.dymetis.com");
            csr.SubjectAlternativeNames.Add("sso.certes-ci.dymetis.com");

            var dirUri = await IntegrationHelper.GetAcmeUriV1();

            using (var client = new AcmeClient(IntegrationHelper.GetAcmeHttpHandler(dirUri)))
            {
                client.Use(accountKey.Export());

                await AuthorizeDns(client, "www.certes-ci.dymetis.com");
                await AuthorizeDns(client, "mail.certes-ci.dymetis.com");
                await AuthorizeDns(client, "sso.certes-ci.dymetis.com");

                // should returns the valid ID
                var authz = await client.NewAuthorization(new AuthorizationIdentifier
                {
                    Type  = AuthorizationIdentifierTypes.Dns,
                    Value = "www.certes-ci.dymetis.com",
                });

                Assert.Equal(EntityStatus.Valid, authz.Data.Status);

                var authzByLoc = await client.GetAuthorization(authz.Location);

                Assert.Equal(authz.Data.Identifier.Value, authzByLoc.Data.Identifier.Value);

                var cert = await client.NewCertificate(csr);

                var pfx = cert.ToPfx();

                pfx.AddTestCert();

                pfx.Build("my.pfx", "abcd1234");
                await client.RevokeCertificate(cert);
            }
        }
Ejemplo n.º 13
0
        private static async Task AuthorizeDns(AcmeClient client, string name)
        {
            var authz = await client.NewAuthorization(new AuthorizationIdentifier
            {
                Type  = AuthorizationIdentifierTypes.Dns,
                Value = name
            });

            var httpChallengeInfo = authz.Data.Challenges
                                    .Where(c => c.Type == ChallengeTypes.Http01).First();
            var httpChallenge = await client.CompleteChallenge(httpChallengeInfo);

            while (authz.Data.Status == EntityStatus.Pending)
            {
                // Wait for ACME server to validate the identifier
                await Task.Delay(1000);

                authz = await client.GetAuthorization(httpChallenge.Location);
            }
        }
Ejemplo n.º 14
0
        public async Task CanIssueSan()
        {
            var csr = new CertificationRequestBuilder();

            csr.AddName("CN=CA, ST=Ontario, L=Toronto, O=Certes, OU=Dev, CN=www.certes-ci.dymetis.com");
            csr.SubjectAlternativeNames.Add("mail.certes-ci.dymetis.com");
            csr.SubjectAlternativeNames.Add("sso.certes-ci.dymetis.com");

            using (var client = new AcmeClient(WellKnownServers.LetsEncryptStaging))
            {
                client.Use(Helper.Loadkey().Export());

                await Task.WhenAll(
                    AuthorizeDns(client, "www.certes-ci.dymetis.com"),
                    AuthorizeDns(client, "mail.certes-ci.dymetis.com"),
                    AuthorizeDns(client, "sso.certes-ci.dymetis.com"));

                var cert = await client.NewCertificate(csr);
            }
        }
Ejemplo n.º 15
0
        public async Task RunAccountFlow(KeyAlgorithm algorithm)
        {
            var dirUri = await IntegrationHelper.GetAcmeUriV1();

            var key = new AccountKey(algorithm);

            using (var client = new AcmeClient(IntegrationHelper.GetAcmeHttpHandler(dirUri)))
            {
                client.Use(key.Export());
                var reg = await client.NewRegistraton();

                reg.Data.Agreement = reg.GetTermsOfServiceUri();

                await client.UpdateRegistration(reg);

                var newKey = new AccountKey().Export();
                await client.ChangeKey(reg, newKey);

                await client.DeleteRegistration(reg);
            }
        }