예제 #1
0
        private async Task ValidateOrderAsync(string[] domains, IOrderContext order)
        {
            var allAuthorizations = await order.Authorizations();

            var challengeContextTasks = new List <Task <IChallengeContext> >();

            challengeContextTasks.AddRange(allAuthorizations.Select(x => x.Http()));

            var challengeContexts = await Task.WhenAll(challengeContextTasks);

            var nonNullChallengeContexts = challengeContexts.Where(x => x != null);

            _logger.LogInformation("Validating all pending order authorizations.");

            var challengeDtos = nonNullChallengeContexts.Select(x => new ChallengeDto()
            {
                Token = x.Type == ChallengeTypes.Dns01 ?
                        acme.AccountKey.DnsTxt(x.Token) :
                        x.Token,
                Response = x.KeyAuthz,
                Domains  = domains
            }).ToArray();

            await _persistenceService.PersistChallengesAsync(challengeDtos);

            try
            {
                var challengeValidationResponses = await ValidateChallengesAsync(nonNullChallengeContexts);

                var nonNullChallengeValidationResponses = challengeValidationResponses.Where(x => x != null).ToArray();

                if (challengeValidationResponses.Length > nonNullChallengeValidationResponses.Length)
                {
                    _logger.LogWarning("Some challenge responses were null.");
                }

                await _persistenceService.DeleteChallengesAsync(challengeDtos);

                var challengeExceptions = nonNullChallengeValidationResponses
                                          .Where(x => x.Status == ChallengeStatus.Invalid)
                                          .Select(x => new Exception($"{x.Error?.Type ?? "errortype null"}: {x.Error?.Detail ?? "null errordetails"} (challenge type {x.Type ?? "null"})"))
                                          .ToArray();

                if (challengeExceptions.Length > 0)
                {
                    throw new OrderInvalidException(
                              "One or more LetsEncrypt orders were invalid. Make sure that LetsEncrypt can contact the domain you are trying to request an SSL certificate for, in order to verify it.",
                              new AggregateException(challengeExceptions));
                }
            }
            finally
            {
                await _persistenceService.DeleteChallengesAsync(challengeDtos);
            }
        }
        public async Task OnNoValidCertificateAvailable_ShouldRenewCertificate()
        {
            // arrange

            PersistenceService.GetPersistedSiteCertificateAsync().Returns(Task.FromResult(InvalidCert));

            var dtos = new [] { new ChallengeDto {
                                    Domains = new[] { "test.com" }, Token = "ping", Response = "pong"
                                } };
            var placedOrder = new PlacedOrder(dtos, Substitute.For <IOrderContext>(), Array.Empty <IChallengeContext>());

            LetsEncryptClient.PlaceOrder(SeqEq(new[] { "test.com" })).Returns(Task.FromResult(placedOrder));
            PersistenceService.PersistChallengesAsync(dtos).Returns(Task.CompletedTask);
            PersistenceService.DeleteChallengesAsync(dtos).Returns(Task.CompletedTask);

            var newCertBytes = SelfSignedCertificate.Make(DateTime.Now, DateTime.Now.AddDays(90)).RawData;

            LetsEncryptClient.FinalizeOrder(placedOrder).Returns(Task.FromResult(new PfxCertificate(newCertBytes)));

            var newCertificate = new LetsEncryptX509Certificate(newCertBytes) as IPersistableCertificate;

            PersistenceService.PersistSiteCertificateAsync(newCertificate).Returns(Task.CompletedTask);

            // act

            var output = await Sut.RenewCertificateIfNeeded(current : null);

            // assert

            output.Status.Should().Be(Renewed);
            ((LetsEncryptX509Certificate)output.Certificate).RawData.Should().BeEquivalentTo(newCertBytes);

            CertificateValidator.Received(1).IsCertificateValid(null);
            await PersistenceService.Received(1).GetPersistedSiteCertificateAsync();

            CertificateValidator.Received(1).IsCertificateValid(InvalidCert);
            await LetsEncryptClient.Received(1).PlaceOrder(SeqEq(new[] { "test.com" }));

            await PersistenceService.Received(1).PersistChallengesAsync(dtos);

            await PersistenceService.Received(1).DeleteChallengesAsync(dtos);

            await PersistenceService.Received(1).PersistChallengesAsync(dtos);

            await LetsEncryptClient.Received(1).FinalizeOrder(placedOrder);

            await LetsEncryptClientFactory.Received(1).GetClient();
        }
예제 #3
0
        private async Task <IAbstractCertificate> RequestNewLetsEncryptCertificate()
        {
            var client = await _clientFactory.GetClient();

            var placedOrder = await client.PlaceOrder(_domains);

            await _persistenceService.PersistChallengesAsync(placedOrder.Challenges);

            try
            {
                var pfxCertificateBytes = await client.FinalizeOrder(placedOrder);

                await _persistenceService.PersistSiteCertificateAsync(new LetsEncryptX509Certificate(pfxCertificateBytes.Bytes));

                const string password = nameof(FluffySpoon);

                return(new LetsEncryptX509Certificate(pfxCertificateBytes.Bytes));
            }
            finally
            {
                await _persistenceService.DeleteChallengesAsync(placedOrder.Challenges);
            }
        }