mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
ipatests: Test if ACME renews the issued cert with cerbot
This test is to check if ACME certificate renews upon reaching expiry related: https://pagure.io/freeipa/issue/4751 Signed-off-by: Mohammad Rizwan <myusuf@redhat.com> ipatests: remove skipif for minimum pki dependency Remove skipif from ACME tests as required pki version updated in freeipa.spec file (pki 10.10.5) Signed-off-by: Mohammad Rizwan <myusuf@redhat.com> ipatests: move common code to separate method Move the code from prepare_acme_client, TestACME/test_certbot_register and TestACME/test_certbot_certonly_standalone to separate method so that it can be re-used in TestACMERenew. Signed-off-by: Mohammad Rizwan <myusuf@redhat.com> Reviewed-By: Florence Blanc-Renaud <flo@redhat.com>
This commit is contained in:
committed by
Florence Blanc-Renaud
parent
a297ebbb8a
commit
d2ca791549
@@ -14,7 +14,6 @@ from ipatests.pytest_ipa.integration import tasks
|
||||
from ipatests.test_integration.test_caless import CALessBase, ipa_certs_cleanup
|
||||
from ipaplatform.osinfo import osinfo
|
||||
from ipaplatform.paths import paths
|
||||
from ipaserver.install import cainstance
|
||||
from ipatests.test_integration.test_external_ca import (
|
||||
install_server_external_ca_step1,
|
||||
install_server_external_ca_step2,
|
||||
@@ -36,6 +35,17 @@ skip_mod_md_tests = osinfo.id not in ['rhel', 'fedora', ]
|
||||
CERTBOT_DNS_IPA_SCRIPT = '/usr/libexec/ipa/acme/certbot-dns-ipa'
|
||||
|
||||
|
||||
def move_date(host, chrony_cmd, date_str):
|
||||
"""Helper method to move system date
|
||||
:param host: host on which date is to be manipulated
|
||||
:param chrony_cmd: systemctl command to apply to
|
||||
chrony service, for instance 'start', 'stop'
|
||||
:param date_str: date string to change the date i.e '3years2months1day1'
|
||||
"""
|
||||
host.run_command(['systemctl', chrony_cmd, 'chronyd'])
|
||||
host.run_command(['date', '-s', date_str])
|
||||
|
||||
|
||||
def check_acme_status(host, exp_status, timeout=60):
|
||||
"""Helper method to check the status of acme server"""
|
||||
for _i in range(0, timeout, 5):
|
||||
@@ -78,8 +88,64 @@ def server_install_teardown(func):
|
||||
return wrapped
|
||||
|
||||
|
||||
@pytest.mark.skipif(not cainstance.minimum_acme_support(),
|
||||
reason="does not provide ACME")
|
||||
def prepare_acme_client(master, client):
|
||||
# cache the acme service uri
|
||||
acme_host = f'{IPA_CA_RECORD}.{master.domain.name}'
|
||||
acme_server = f'https://{acme_host}/acme/directory'
|
||||
|
||||
# install acme client packages
|
||||
if not skip_certbot_tests:
|
||||
tasks.install_packages(client, ['certbot'])
|
||||
if not skip_mod_md_tests:
|
||||
tasks.install_packages(client, ['mod_md'])
|
||||
|
||||
return acme_server
|
||||
|
||||
|
||||
def certbot_register(host, acme_server):
|
||||
"""method to register the host to acme server"""
|
||||
# clean up any existing registration and certificates
|
||||
host.run_command(
|
||||
[
|
||||
'rm', '-rf',
|
||||
'/etc/letsencrypt/accounts',
|
||||
'/etc/letsencrypt/archive',
|
||||
'/etc/letsencrypt/csr',
|
||||
'/etc/letsencrypt/keys',
|
||||
'/etc/letsencrypt/live',
|
||||
'/etc/letsencrypt/renewal',
|
||||
'/etc/letsencrypt/renewal-hooks'
|
||||
]
|
||||
)
|
||||
# service is enabled; registration should succeed
|
||||
host.run_command(
|
||||
[
|
||||
'certbot',
|
||||
'--server', acme_server,
|
||||
'register',
|
||||
'-m', 'nobody@example.test',
|
||||
'--agree-tos',
|
||||
'--no-eff-email',
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
def certbot_standalone_cert(host, acme_server):
|
||||
"""method to issue a certbot's certonly standalone cert"""
|
||||
# Get a cert from ACME service using HTTP challenge and Certbot's
|
||||
# standalone HTTP server mode
|
||||
host.run_command(['systemctl', 'stop', 'httpd'])
|
||||
host.run_command(
|
||||
[
|
||||
'certbot',
|
||||
'--server', acme_server,
|
||||
'certonly',
|
||||
'--domain', host.hostname,
|
||||
'--standalone',
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class TestACME(CALessBase):
|
||||
"""
|
||||
Test the FreeIPA ACME service by using ACME clients on a FreeIPA client.
|
||||
@@ -107,24 +173,12 @@ class TestACME(CALessBase):
|
||||
num_replicas = 1
|
||||
num_clients = 1
|
||||
|
||||
@classmethod
|
||||
def prepare_acme_client(cls):
|
||||
# cache the acme service uri
|
||||
acme_host = f'{IPA_CA_RECORD}.{cls.master.domain.name}'
|
||||
cls.acme_server = f'https://{acme_host}/acme/directory'
|
||||
|
||||
# install acme client packages
|
||||
if not skip_certbot_tests:
|
||||
tasks.install_packages(cls.clients[0], ['certbot'])
|
||||
if not skip_mod_md_tests:
|
||||
tasks.install_packages(cls.clients[0], ['mod_md'])
|
||||
|
||||
@classmethod
|
||||
def install(cls, mh):
|
||||
super(TestACME, cls).install(mh)
|
||||
|
||||
# install packages before client install in case of IPA DNS problems
|
||||
cls.prepare_acme_client()
|
||||
cls.acme_server = prepare_acme_client(cls.master, cls.clients[0])
|
||||
|
||||
# Each subclass handles its own server installation procedure
|
||||
if cls.__name__ != 'TestACME':
|
||||
@@ -212,45 +266,11 @@ class TestACME(CALessBase):
|
||||
|
||||
@pytest.mark.skipif(skip_certbot_tests, reason='certbot not available')
|
||||
def test_certbot_register(self):
|
||||
# clean up any existing registration and certificates
|
||||
self.clients[0].run_command(
|
||||
[
|
||||
'rm', '-rf',
|
||||
'/etc/letsencrypt/accounts',
|
||||
'/etc/letsencrypt/archive',
|
||||
'/etc/letsencrypt/csr',
|
||||
'/etc/letsencrypt/keys',
|
||||
'/etc/letsencrypt/live',
|
||||
'/etc/letsencrypt/renewal',
|
||||
'/etc/letsencrypt/renewal-hooks'
|
||||
]
|
||||
)
|
||||
# service is enabled; registration should succeed
|
||||
self.clients[0].run_command(
|
||||
[
|
||||
'certbot',
|
||||
'--server', self.acme_server,
|
||||
'register',
|
||||
'-m', 'nobody@example.test',
|
||||
'--agree-tos',
|
||||
'--no-eff-email',
|
||||
],
|
||||
)
|
||||
certbot_register(self.clients[0], self.acme_server)
|
||||
|
||||
@pytest.mark.skipif(skip_certbot_tests, reason='certbot not available')
|
||||
def test_certbot_certonly_standalone(self):
|
||||
# Get a cert from ACME service using HTTP challenge and Certbot's
|
||||
# standalone HTTP server mode
|
||||
self.clients[0].run_command(['systemctl', 'stop', 'httpd'])
|
||||
self.clients[0].run_command(
|
||||
[
|
||||
'certbot',
|
||||
'--server', self.acme_server,
|
||||
'certonly',
|
||||
'--domain', self.clients[0].hostname,
|
||||
'--standalone',
|
||||
],
|
||||
)
|
||||
certbot_standalone_cert(self.clients[0], self.acme_server)
|
||||
|
||||
@pytest.mark.skipif(skip_certbot_tests, reason='certbot not available')
|
||||
def test_certbot_revoke(self):
|
||||
@@ -417,8 +437,6 @@ class TestACME(CALessBase):
|
||||
assert "invalid 'certificate'" in result.stderr_text
|
||||
|
||||
|
||||
@pytest.mark.skipif(not cainstance.minimum_acme_support(),
|
||||
reason="does not provide ACME")
|
||||
class TestACMECALess(IntegrationTest):
|
||||
"""Test to check the CA less replica setup"""
|
||||
num_replicas = 1
|
||||
@@ -542,3 +560,84 @@ class TestACMEwithExternalCA(TestACME):
|
||||
|
||||
tasks.install_client(cls.master, cls.clients[0])
|
||||
tasks.install_replica(cls.master, cls.replicas[0])
|
||||
|
||||
|
||||
class TestACMERenew(IntegrationTest):
|
||||
|
||||
num_clients = 1
|
||||
|
||||
@classmethod
|
||||
def install(cls, mh):
|
||||
|
||||
# install packages before client install in case of IPA DNS problems
|
||||
cls.acme_server = prepare_acme_client(cls.master, cls.clients[0])
|
||||
|
||||
tasks.install_master(cls.master, setup_dns=True)
|
||||
tasks.install_client(cls.master, cls.clients[0])
|
||||
|
||||
@pytest.fixture
|
||||
def issue_and_expire_cert(self):
|
||||
"""Fixture to expire cert by moving date past expiry of acme cert"""
|
||||
# enable the ACME service on master
|
||||
self.master.run_command(['ipa-acme-manage', 'enable'])
|
||||
|
||||
# register the account with certbot
|
||||
certbot_register(self.clients[0], self.acme_server)
|
||||
|
||||
# request a standalone acme cert
|
||||
certbot_standalone_cert(self.clients[0], self.acme_server)
|
||||
|
||||
cmd_input = (
|
||||
# Password for admin@{REALM}:
|
||||
"{pwd}\n"
|
||||
# Password expired. You must change it now.
|
||||
# Enter new password:
|
||||
"{pwd}\n"
|
||||
# Enter it again:
|
||||
"{pwd}\n"
|
||||
)
|
||||
# move system date to expire acme cert
|
||||
for host in self.clients[0], self.master:
|
||||
host.run_command(['kdestroy', '-A'])
|
||||
move_date(host, 'stop', '+90days')
|
||||
self.clients[0].run_command(
|
||||
['kinit', 'admin'],
|
||||
stdin_text=cmd_input.format(
|
||||
pwd=self.clients[0].config.admin_password
|
||||
)
|
||||
)
|
||||
|
||||
yield
|
||||
|
||||
# move back date
|
||||
for host in self.clients[0], self.master:
|
||||
host.run_command(['kdestroy', '-A'])
|
||||
move_date(host, 'start', '-90days')
|
||||
tasks.kinit_admin(host)
|
||||
|
||||
@pytest.mark.skipif(skip_certbot_tests, reason='certbot not available')
|
||||
def test_renew(self, issue_and_expire_cert):
|
||||
"""Test if ACME renews the issued cert with cerbot
|
||||
|
||||
This test is to check if ACME certificate renews upon
|
||||
reaching expiry
|
||||
|
||||
related: https://pagure.io/freeipa/issue/4751
|
||||
"""
|
||||
data = self.clients[0].get_file_contents(
|
||||
f'/etc/letsencrypt/live/{self.clients[0].hostname}/cert.pem'
|
||||
)
|
||||
cert = x509.load_pem_x509_certificate(data, backend=default_backend())
|
||||
initial_expiry = cert.not_valid_after
|
||||
|
||||
tasks.kinit_admin(self.clients[0])
|
||||
|
||||
self.clients[0].run_command(['certbot', 'renew'])
|
||||
|
||||
data = self.clients[0].get_file_contents(
|
||||
f'/etc/letsencrypt/live/{self.clients[0].hostname}/cert.pem'
|
||||
)
|
||||
cert = x509.load_pem_x509_certificate(data, backend=default_backend())
|
||||
renewed_expiry = cert.not_valid_after
|
||||
|
||||
assert initial_expiry != renewed_expiry
|
||||
|
||||
Reference in New Issue
Block a user