public Task PersistAsync(CertificateType persistenceType, IPersistableCertificate certificate) { switch (persistenceType) { case CertificateType.Account: _accountCertificate = (IKeyCertificate)certificate; break; case CertificateType.Site: _siteCertificate = certificate; break; default: throw new ArgumentException("Unhandled persistence type", nameof(persistenceType)); } return(Task.CompletedTask); }
public async Task <CertificateRenewalResult> RenewCertificateIfNeeded(IAbstractCertificate current = null) { _logger.LogInformation("Checking to see if in-memory LetsEncrypt certificate needs renewal."); if (_certificateValidator.IsCertificateValid(current)) { _logger.LogInformation("Current in-memory LetsEncrypt certificate is valid."); return(new CertificateRenewalResult(current, CertificateRenewalStatus.Unchanged)); } _logger.LogInformation("Checking to see if existing LetsEncrypt certificate has been persisted and is valid."); var persistedSiteCertificate = await _persistenceService.GetPersistedSiteCertificateAsync(); if (_certificateValidator.IsCertificateValid(persistedSiteCertificate)) { _logger.LogInformation("A persisted non-expired LetsEncrypt certificate was found and will be used: {Thumbprint}", persistedSiteCertificate.Thumbprint); return(new CertificateRenewalResult(persistedSiteCertificate, CertificateRenewalStatus.LoadedFromStore)); } _logger.LogInformation("No valid certificate was found. Requesting new certificate from LetsEncrypt."); var newCertificate = await RequestNewLetsEncryptCertificate(); return(new CertificateRenewalResult(newCertificate, CertificateRenewalStatus.Renewed)); }
public bool IsCertificateValid(IAbstractCertificate certificate) { try { if (certificate == null) { return(false); } var now = DateTime.Now; _logger.LogTrace("Validating cert UntilExpiry {UntilExpiry}, AfterIssue {AfterIssue} - {Certificate}", _options.TimeUntilExpiryBeforeRenewal, _options.TimeAfterIssueDateBeforeRenewal, certificate); if (_options.TimeUntilExpiryBeforeRenewal != null && certificate.NotAfter - now < _options.TimeUntilExpiryBeforeRenewal) { return(false); } if (_options.TimeAfterIssueDateBeforeRenewal != null && now - certificate.NotBefore > _options.TimeAfterIssueDateBeforeRenewal) { return(false); } if (certificate.NotBefore > now || certificate.NotAfter < now) { return(false); } return(true); } catch (CryptographicException exc) { _logger.LogError(exc, "Exception occured during certificate validation"); return(false); } }
public async Task RunOnceAsync() { if (_semaphoreSlim.CurrentCount == 0) { return; } await _semaphoreSlim.WaitAsync(); try { var result = await _certificateProvider.RenewCertificateIfNeeded(Certificate); if (result.Status != Unchanged) { // Preload intermediate certs before exposing certificate to the Kestrel using var chain = new X509Chain { ChainPolicy = { RevocationMode = X509RevocationMode.NoCheck } }; if (result.Certificate is LetsEncryptX509Certificate x509cert) { if (chain.Build(x509cert.GetCertificate())) { _logger.LogInformation("Successfully built certificate chain"); } else { _logger.LogWarning( "Was not able to build certificate chain. This can cause an outage of your app."); } } } Certificate = result.Certificate; if (result.Status == Renewed) { foreach (var lifecycleHook in _lifecycleHooks) { await lifecycleHook.OnRenewalSucceededAsync(); } } } catch (Exception ex) { foreach (var lifecycleHook in _lifecycleHooks) { await lifecycleHook.OnExceptionAsync(ex); } throw; } finally { _semaphoreSlim.Release(); } }
public CertificateRenewalResult(IAbstractCertificate certificate, CertificateRenewalStatus status) { Certificate = certificate; Status = status; }