private async Task ValidateChallenges(IChallengeContext[] challengeContexts, AcmeOrderOptions orderOptions) { _logger.LogInformation("[LetsEncrypt][Validating] all pending order authorizations."); var challengeValidationResponses = await ValidateChallengesAsync(challengeContexts, orderOptions); var nonNullChallengeValidationResponses = challengeValidationResponses.Where(x => x != null).ToArray(); if (challengeValidationResponses.Length > nonNullChallengeValidationResponses.Length) { _logger.LogInformation("[LetsEncrypt][Validating] Some challenge responses were null."); } 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 LetsEncryptException( "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)); } _logger.LogInformation("[LetsEncrypt][Validating] Completed."); }
private async Task <byte[]> AcquireCertificateBytesFromOrderAsync( IOrderContext order, AcmeOrderOptions orderOptions, AcmeAccountOptions accountOptions, CertificateOptions certificateOptions) { _logger.LogInformation("[LetsEncrypt][Certificate] Acquiring certificate through signing request."); var privateKey = KeyFactory.NewKey((Certes.KeyAlgorithm)orderOptions.KeyAlgorithm); if (orderOptions?.CertificateSigningRequest == null) { var commonName = accountOptions.Domains[0]; _logger.LogDebug("Creating cert for {commonName}", commonName); var csrInfo = new CsrInfo { CommonName = commonName, }; if (orderOptions != null) { orderOptions.CertificateSigningRequest = csrInfo; } } var certificateChain = await order.Generate(orderOptions?.CertificateSigningRequest, privateKey); var pfxBuilder = certificateChain.ToPfx(privateKey); pfxBuilder.FullChain = true; var pfxBytes = pfxBuilder.Build( $"Let's Encrypt - {accountOptions.Domains[0]} ", certificateOptions?.CertificatePassword ?? string.Empty); _logger.LogInformation("[LetsEncrypt][Certificate] Certificate acquired."); return(pfxBytes); }
private async Task <Challenge[]> ValidateChallengesAsync(IChallengeContext[] challengeContexts, AcmeOrderOptions orderOptions) { var challenges = await Task.WhenAll(challengeContexts.Select(x => x.Validate())); var retries = 0; var delay = TimeSpan.FromSeconds(orderOptions.ValidationDelay); while (true) { var anyValid = challenges.Any(x => x.Status == ChallengeStatus.Valid); var anyPending = challenges.Any(x => x.Status == ChallengeStatus.Pending); var allInvalid = challenges.All(x => (x.Status == ChallengeStatus.Invalid && x.Type == ChallengeTypes.Http01)); if ((anyValid && !anyPending) || (allInvalid && retries >= orderOptions.ValidationRetry)) { break; } if (retries >= orderOptions.ValidationRetry) { break; } await Task.Delay(delay); challenges = await Task.WhenAll(challengeContexts.Select(x => x.Resource())); retries++; } return(challenges); }