letsencrypt: Re-obtain certificates during repair

- Set check_id and domain for domain diagnostic check

- If there is an error, store it in thread local storage.

- Drop checking for case when no domain is configured. This is better done after
initial setup via notification rather than in diagnostics. Proposed change also
will not show the warning if a .local domain is configured (almost always). Keep
checking for Check id to deal with older stored diagnostic results.

- Call obtain when certificate is not available. Call re-obtain otherwise. This
is important for properly calling the post-obtain operations.

Signed-off-by: James Valleroy <jvalleroy@mailbox.org>
[sunil: Drop check for case when no domain is configured]
[sunil: Call either obtain or re-obtain based on current state of certificate]
Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: Sunil Mohan Adapa <sunil@medhas.org>
This commit is contained in:
James Valleroy 2024-04-20 18:59:14 -04:00 committed by Sunil Mohan Adapa
parent f5f687c8fd
commit 8ff1a14e84
No known key found for this signature in database
GPG Key ID: 43EA1CFF0AA7C5F2

View File

@ -17,6 +17,7 @@ from plinth.modules.apache.components import diagnose_url
from plinth.modules.backups.components import BackupRestore
from plinth.modules.names.components import DomainType
from plinth.package import Packages
from plinth.setup import store_error_message
from plinth.signals import domain_added, domain_removed, post_app_loading
from plinth.utils import format_lazy
@ -96,17 +97,40 @@ class LetsEncryptApp(app_module.App):
for domain in names.components.DomainName.list():
if domain.domain_type.can_have_certificate:
results.append(diagnose_url('https://' + domain.name))
if not results:
results.append(
DiagnosticCheck(
'letsencrypt-cannot-test',
gettext_noop('Cannot test: No domains are configured.'),
Result.WARNING))
result = diagnose_url('https://' + domain.name)
result.check_id = f'letsencrypt-domain-{domain.name}'
result.parameters['domain'] = domain.name
results.append(result)
return results
def repair(self, failed_checks: list) -> bool:
"""Try to repair failed diagnostics.
Returns whether the app setup should be re-run.
"""
status = get_status()
# Obtain/re-obtain certificates for failing domains
for failed_check in failed_checks:
if not failed_check.check_id.startswith('letsencrypt-domain'):
continue
domain = failed_check.parameters['domain']
try:
domain_status = status['domains'][domain]
if domain_status.get('certificate_available', False):
certificate_obtain(domain)
else:
certificate_reobtain(domain)
except Exception as error:
# This happens if a non-functional domain is configured.
logger.error('Could not re-obtain certificate: %s', error)
# Add the error message to thread local storage
store_error_message(str(error))
return False
def setup(self, old_version):
"""Install and configure the app."""
super().setup(old_version)