letsencrypt: Handle cert setup when an app wants all domains

Currently, when domains is for an app's LE component is set as '*'. Calling
setup_certificates() results in copying certificate for the '*' domain instead
copying certificates for each of the domains on the system. Fix this by
implementing a special case where certificates are copied for all domains that
can have certificates.

Tests:

- Implement and run unit tests.

- Certificates are copied to /etc/{postfix,dovecot}/letsencrypt/ when email
server uses LE components with '*' for domains parameter.

Signed-off-by: Sunil Mohan Adapa <sunil@medhas.org>
Reviewed-by: James Valleroy <jvalleroy@mailbox.org>
This commit is contained in:
Sunil Mohan Adapa 2021-12-08 11:13:53 -08:00 committed by James Valleroy
parent 84f12d8633
commit aff62d4d85
No known key found for this signature in database
GPG Key ID: 77C0C75E7B650808
2 changed files with 40 additions and 0 deletions

View File

@ -9,6 +9,7 @@ import pathlib
import threading
from plinth import actions, app
from plinth.modules.names.components import DomainName
logger = logging.getLogger(__name__)
@ -151,6 +152,12 @@ class LetsEncrypt(app.FollowerComponent):
if not app_domains:
app_domains = self.domains
if app_domains == '*':
# Setup for all domains and not just ones that LE can obtain
# certificate for. This allows the domains that can't have LE
# certificate to work with self-signed certificates.
app_domains = DomainName.list_names()
domains, status = self._get_letsencrypt_domains()
if self.should_copy_certificates:

View File

@ -9,6 +9,7 @@ from unittest.mock import call, patch
import pytest
from plinth.modules.letsencrypt.components import LetsEncrypt
from plinth.modules.names.components import DomainName, DomainType
@pytest.fixture(name='empty_letsencrypt_list', autouse=True)
@ -46,6 +47,24 @@ def fixture_get_status():
yield get_status
@pytest.fixture(name='domain_list')
def fixture_domain_list():
"""Return patch DomainName.list() method."""
method = 'plinth.modules.names.components.DomainName.list'
with patch(method) as domain_list:
DomainType._all = {}
DomainType('domain-type-1', 'type-1', 'url1', False)
DomainType('domain-type-2', 'type-2', 'url1', True)
domain1 = DomainName('domain-name-1', 'invalid1.example',
'domain-type-1', '__all__')
domain2 = DomainName('domain-name-2', 'valid.example', 'domain-type-2',
'__all__')
domain3 = DomainName('domain-name-3', 'invalid2.example',
'domain-type-2', '__all__')
domain_list.return_value = [domain1, domain2, domain3]
yield domain_list
@pytest.fixture(name='superuser_run')
def fixture_superuser_run():
"""Return patched plinth.actions.superuser_run() method."""
@ -196,6 +215,20 @@ def test_setup_certificates_with_app_domains(superuser_run, get_status,
_assert_restarted_daemons(component.daemons, superuser_run)
def test_setup_certificates_with_all_domains(domain_list, superuser_run,
get_status, component):
"""Test that initial copying for certs works when app domains is '*'."""
component._domains = '*'
component.setup_certificates()
_assert_copy_certificate_called(
component, superuser_run, {
'valid.example': 'valid',
'invalid1.example': 'invalid',
'invalid2.example': 'invalid'
})
_assert_restarted_daemons(component.daemons, superuser_run)
def _assert_compare_certificate_called(component, superuser_run, domains):
"""Check that compare certificate was called properly."""
expected_calls = []