mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-23 07:33:27 -06:00
ipatests: tests for certificate pruning
1. Test to prune the expired certificate by manual run 2. Test to prune expired certificate by cron job 3. Test to prune expired certificate with retention unit option 4. Test to prune expired certificate with search size limit option 5. Test to check config-show command shows set param 6. Test prune command shows proper status after disabling the pruning related: https://pagure.io/freeipa/issue/9294 Signed-off-by: Mohammad Rizwan <myusuf@redhat.com> Reviewed-By: Rob Crittenden <rcritten@redhat.com>
This commit is contained in:
parent
0b762d2b2a
commit
828f6e7c92
@ -122,21 +122,23 @@ def certbot_register(host, acme_server):
|
||||
)
|
||||
|
||||
|
||||
def certbot_standalone_cert(host, acme_server):
|
||||
def certbot_standalone_cert(host, acme_server, no_of_cert=1):
|
||||
"""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',
|
||||
'--key-type', 'rsa',
|
||||
]
|
||||
)
|
||||
for _i in range(0, no_of_cert):
|
||||
host.run_command(
|
||||
[
|
||||
'certbot',
|
||||
'--server', acme_server,
|
||||
'certonly',
|
||||
'--domain', host.hostname,
|
||||
'--standalone',
|
||||
'--key-type', 'rsa',
|
||||
'--force-renewal'
|
||||
]
|
||||
)
|
||||
|
||||
|
||||
class TestACME(CALessBase):
|
||||
@ -573,6 +575,56 @@ class TestACMEwithExternalCA(TestACME):
|
||||
tasks.install_replica(cls.master, cls.replicas[0])
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def issue_and_expire_acme_cert():
|
||||
"""Fixture to expire cert by moving date past expiry of acme cert"""
|
||||
hosts = []
|
||||
|
||||
def _issue_and_expire_acme_cert(
|
||||
master, client,
|
||||
acme_server_url, no_of_cert=1
|
||||
):
|
||||
|
||||
hosts.append(master)
|
||||
hosts.append(client)
|
||||
|
||||
# enable the ACME service on master
|
||||
master.run_command(['ipa-acme-manage', 'enable'])
|
||||
|
||||
# register the account with certbot
|
||||
certbot_register(client, acme_server_url)
|
||||
|
||||
# request a standalone acme cert
|
||||
certbot_standalone_cert(client, acme_server_url, no_of_cert)
|
||||
|
||||
# move system date to expire acme cert
|
||||
for host in hosts:
|
||||
tasks.kdestroy_all(host)
|
||||
tasks.move_date(host, 'stop', '+90days')
|
||||
|
||||
time.sleep(10)
|
||||
tasks.get_kdcinfo(host)
|
||||
# Note raiseonerr=False:
|
||||
# the assert is located after kdcinfo retrieval.
|
||||
result = master.run_command(
|
||||
"KRB5_TRACE=/dev/stdout kinit admin",
|
||||
stdin_text='{0}\n{0}\n{0}\n'.format(
|
||||
master.config.admin_password
|
||||
),
|
||||
raiseonerr=False
|
||||
)
|
||||
# Retrieve kdc.$REALM after the password change, just in case SSSD
|
||||
# domain status flipped to online during the password change.
|
||||
tasks.get_kdcinfo(host)
|
||||
assert result.returncode == 0
|
||||
|
||||
yield _issue_and_expire_acme_cert
|
||||
|
||||
# move back date
|
||||
for host in hosts:
|
||||
tasks.move_date(host, 'start', '-90days')
|
||||
|
||||
|
||||
class TestACMERenew(IntegrationTest):
|
||||
|
||||
num_clients = 1
|
||||
@ -586,48 +638,8 @@ class TestACMERenew(IntegrationTest):
|
||||
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)
|
||||
|
||||
# move system date to expire acme cert
|
||||
for host in self.clients[0], self.master:
|
||||
tasks.kdestroy_all(host)
|
||||
tasks.move_date(host, 'stop', '+90days')
|
||||
|
||||
tasks.get_kdcinfo(host)
|
||||
# Note raiseonerr=False:
|
||||
# the assert is located after kdcinfo retrieval.
|
||||
result = host.run_command(
|
||||
"KRB5_TRACE=/dev/stdout kinit admin",
|
||||
stdin_text='{0}\n{0}\n{0}\n'.format(
|
||||
self.clients[0].config.admin_password
|
||||
),
|
||||
raiseonerr=False
|
||||
)
|
||||
# Retrieve kdc.$REALM after the password change, just in case SSSD
|
||||
# domain status flipped to online during the password change.
|
||||
tasks.get_kdcinfo(host)
|
||||
assert result.returncode == 0
|
||||
|
||||
yield
|
||||
|
||||
# move back date
|
||||
for host in self.clients[0], self.master:
|
||||
tasks.kdestroy_all(host)
|
||||
tasks.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):
|
||||
def test_renew(self, issue_and_expire_acme_cert):
|
||||
"""Test if ACME renews the issued cert with cerbot
|
||||
|
||||
This test is to check if ACME certificate renews upon
|
||||
@ -635,6 +647,8 @@ class TestACMERenew(IntegrationTest):
|
||||
|
||||
related: https://pagure.io/freeipa/issue/4751
|
||||
"""
|
||||
issue_and_expire_acme_cert(
|
||||
self.master, self.clients[0], self.acme_server)
|
||||
data = self.clients[0].get_file_contents(
|
||||
f'/etc/letsencrypt/live/{self.clients[0].hostname}/cert.pem'
|
||||
)
|
||||
@ -656,6 +670,7 @@ class TestACMEPrune(IntegrationTest):
|
||||
"""Validate that ipa-acme-manage configures dogtag for pruning"""
|
||||
|
||||
random_serial = True
|
||||
num_clients = 1
|
||||
|
||||
@classmethod
|
||||
def install(cls, mh):
|
||||
@ -663,6 +678,8 @@ class TestACMEPrune(IntegrationTest):
|
||||
raise pytest.skip("RNSv3 not supported")
|
||||
tasks.install_master(cls.master, setup_dns=True,
|
||||
random_serial=True)
|
||||
cls.acme_server = prepare_acme_client(cls.master, cls.clients[0])
|
||||
tasks.install_client(cls.master, cls.clients[0])
|
||||
|
||||
@classmethod
|
||||
def uninstall(cls, mh):
|
||||
@ -718,7 +735,7 @@ class TestACMEPrune(IntegrationTest):
|
||||
['ipa-acme-manage', 'pruning',
|
||||
'--requestretention=60',
|
||||
'--requestretentionunit=minute',
|
||||
'--requestresearchsizelimit=2000',
|
||||
'--requestsearchsizelimit=2000',
|
||||
'--requestsearchtimelimit=5',]
|
||||
)
|
||||
cs_cfg = self.master.get_file_contents(paths.CA_CS_CFG_PATH)
|
||||
@ -741,7 +758,7 @@ class TestACMEPrune(IntegrationTest):
|
||||
|
||||
self.master.run_command(
|
||||
['ipa-acme-manage', 'pruning',
|
||||
'--cron="0 23 1 * *',]
|
||||
'--cron=0 23 1 * *',]
|
||||
)
|
||||
cs_cfg = self.master.get_file_contents(paths.CA_CS_CFG_PATH)
|
||||
assert (
|
||||
@ -760,7 +777,7 @@ class TestACMEPrune(IntegrationTest):
|
||||
'--enable', '--disable'],
|
||||
raiseonerr=False
|
||||
)
|
||||
assert result.returncode == 1
|
||||
assert result.returncode == 2
|
||||
assert "Cannot both enable and disable" in result.stderr_text
|
||||
|
||||
for cmd in ('--config-show', '--run'):
|
||||
@ -769,20 +786,20 @@ class TestACMEPrune(IntegrationTest):
|
||||
cmd, '--enable'],
|
||||
raiseonerr=False
|
||||
)
|
||||
assert result.returncode == 1
|
||||
assert result.returncode == 2
|
||||
assert "Cannot change and show config" in result.stderr_text
|
||||
|
||||
result = self.master.run_command(
|
||||
['ipa-acme-manage', 'pruning',
|
||||
'--cron="* *"'],
|
||||
'--cron=* *'],
|
||||
raiseonerr=False
|
||||
)
|
||||
assert result.returncode == 1
|
||||
assert "Invalid format format --cron" in result.stderr_text
|
||||
assert result.returncode == 2
|
||||
assert "Invalid format for --cron" in result.stderr_text
|
||||
|
||||
result = self.master.run_command(
|
||||
['ipa-acme-manage', 'pruning',
|
||||
'--cron="100 * * * *"'],
|
||||
'--cron=100 * * * *'],
|
||||
raiseonerr=False
|
||||
)
|
||||
assert result.returncode == 1
|
||||
@ -790,8 +807,205 @@ class TestACMEPrune(IntegrationTest):
|
||||
|
||||
result = self.master.run_command(
|
||||
['ipa-acme-manage', 'pruning',
|
||||
'--cron="10 1-5 * * *"'],
|
||||
'--cron=10 1-5 * * *'],
|
||||
raiseonerr=False
|
||||
)
|
||||
assert result.returncode == 1
|
||||
assert "1-5 ranges are not supported" in result.stderr_text
|
||||
|
||||
def test_prune_cert_manual(self, issue_and_expire_acme_cert):
|
||||
"""Test to prune expired certificate by manual run"""
|
||||
if (tasks.get_pki_version(self.master)
|
||||
< tasks.parse_version('11.3.0')):
|
||||
raise pytest.skip("Certificate pruning is not available")
|
||||
|
||||
issue_and_expire_acme_cert(
|
||||
self.master, self.clients[0], self.acme_server)
|
||||
|
||||
# check that the certificate issued for the client
|
||||
result = self.master.run_command(
|
||||
['ipa', 'cert-find', '--subject', self.clients[0].hostname]
|
||||
)
|
||||
assert f'CN={self.clients[0].hostname}' in result.stdout_text
|
||||
|
||||
# run prune command manually
|
||||
self.master.run_command(['ipa-acme-manage', 'pruning', '--enable'])
|
||||
self.master.run_command(['ipactl', 'restart'])
|
||||
self.master.run_command(['ipa-acme-manage', 'pruning', '--run'])
|
||||
# wait for cert to get prune
|
||||
time.sleep(50)
|
||||
|
||||
# check if client cert is removed
|
||||
result = self.master.run_command(
|
||||
['ipa', 'cert-find', '--subject', self.clients[0].hostname],
|
||||
raiseonerr=False
|
||||
)
|
||||
assert f'CN={self.clients[0].hostname}' not in result.stdout_text
|
||||
|
||||
def test_prune_cert_cron(self, issue_and_expire_acme_cert):
|
||||
"""Test to prune expired certificate by cron job"""
|
||||
if (tasks.get_pki_version(self.master)
|
||||
< tasks.parse_version('11.3.0')):
|
||||
raise pytest.skip("Certificate pruning is not available")
|
||||
|
||||
issue_and_expire_acme_cert(
|
||||
self.master, self.clients[0], self.acme_server)
|
||||
|
||||
# check that the certificate issued for the client
|
||||
result = self.master.run_command(
|
||||
['ipa', 'cert-find', '--subject', self.clients[0].hostname]
|
||||
)
|
||||
assert f'CN={self.clients[0].hostname}' in result.stdout_text
|
||||
|
||||
# enable pruning
|
||||
self.master.run_command(['ipa-acme-manage', 'pruning', '--enable'])
|
||||
|
||||
# cron would be set to run the next minute
|
||||
cron_minute = self.master.run_command(
|
||||
[
|
||||
"python3",
|
||||
"-c",
|
||||
(
|
||||
"from datetime import datetime; "
|
||||
"print(int(datetime.now().strftime('%M')) + 5)"
|
||||
),
|
||||
]
|
||||
).stdout_text.strip()
|
||||
self.master.run_command(
|
||||
['ipa-acme-manage', 'pruning',
|
||||
f'--cron={cron_minute} * * * *']
|
||||
)
|
||||
self.master.run_command(['ipactl', 'restart'])
|
||||
# wait for 5 minutes to cron to execute and 20 sec for just in case
|
||||
time.sleep(320)
|
||||
|
||||
# check if client cert is removed
|
||||
result = self.master.run_command(
|
||||
['ipa', 'cert-find', '--subject', self.clients[0].hostname],
|
||||
raiseonerr=False
|
||||
)
|
||||
assert f'CN={self.clients[0].hostname}' not in result.stdout_text
|
||||
|
||||
def test_prune_cert_retention_unit(self, issue_and_expire_acme_cert):
|
||||
"""Test to prune expired certificate with retention unit option"""
|
||||
if (tasks.get_pki_version(self.master)
|
||||
< tasks.parse_version('11.3.0')):
|
||||
raise pytest.skip("Certificate pruning is not available")
|
||||
issue_and_expire_acme_cert(
|
||||
self.master, self.clients[0], self.acme_server)
|
||||
|
||||
# check that the certificate issued for the client
|
||||
result = self.master.run_command(
|
||||
['ipa', 'cert-find', '--subject', self.clients[0].hostname]
|
||||
)
|
||||
assert f'CN={self.clients[0].hostname}' in result.stdout_text
|
||||
|
||||
# enable pruning
|
||||
self.master.run_command(['ipa-acme-manage', 'pruning', '--enable'])
|
||||
|
||||
# certretention set to 5 min
|
||||
self.master.run_command(
|
||||
['ipa-acme-manage', 'pruning',
|
||||
'--certretention=5', '--certretentionunit=minute']
|
||||
)
|
||||
self.master.run_command(['ipactl', 'restart'])
|
||||
|
||||
# wait for 5 min and check if expired cert is removed
|
||||
time.sleep(310)
|
||||
self.master.run_command(['ipa-acme-manage', 'pruning', '--run'])
|
||||
result = self.master.run_command(
|
||||
['ipa', 'cert-find', '--subject', self.clients[0].hostname],
|
||||
raiseonerr=False
|
||||
)
|
||||
assert f'CN={self.clients[0].hostname}' not in result.stdout_text
|
||||
|
||||
def test_prune_cert_search_size_limit(self, issue_and_expire_acme_cert):
|
||||
"""Test to prune expired certificate with search size limit option"""
|
||||
if (tasks.get_pki_version(self.master)
|
||||
< tasks.parse_version('11.3.0')):
|
||||
raise pytest.skip("Certificate pruning is not available")
|
||||
no_of_cert = 10
|
||||
search_size_limit = 5
|
||||
issue_and_expire_acme_cert(
|
||||
self.master, self.clients[0], self.acme_server, no_of_cert)
|
||||
|
||||
# check that the certificate issued for the client
|
||||
result = self.master.run_command(
|
||||
['ipa', 'cert-find', '--subject', self.clients[0].hostname]
|
||||
)
|
||||
assert f'CN={self.clients[0].hostname}' in result.stdout_text
|
||||
assert f'Number of entries returned {no_of_cert}'
|
||||
|
||||
# enable pruning
|
||||
self.master.run_command(['ipa-acme-manage', 'pruning', '--enable'])
|
||||
|
||||
# certretention set to 5 min
|
||||
self.master.run_command(
|
||||
['ipa-acme-manage', 'pruning',
|
||||
f'--certsearchsizelimit={search_size_limit}',
|
||||
'--certsearchtimelimit=100']
|
||||
)
|
||||
self.master.run_command(['ipactl', 'restart'])
|
||||
|
||||
# prune the certificates
|
||||
self.master.run_command(['ipa-acme-manage', 'pruning', '--run'])
|
||||
|
||||
# check if 5 expired cert is removed
|
||||
result = self.master.run_command(
|
||||
['ipa', 'cert-find', '--subject', self.clients[0].hostname]
|
||||
)
|
||||
assert f'Number of entries returned {no_of_cert - search_size_limit}'
|
||||
|
||||
def test_prune_config_show(self, issue_and_expire_acme_cert):
|
||||
"""Test to check config-show command shows set param"""
|
||||
if (tasks.get_pki_version(self.master)
|
||||
< tasks.parse_version('11.3.0')):
|
||||
raise pytest.skip("Certificate pruning is not available")
|
||||
|
||||
self.master.run_command(['ipa-acme-manage', 'pruning', '--enable'])
|
||||
self.master.run_command(
|
||||
['ipa-acme-manage', 'pruning',
|
||||
'--cron=0 0 1 * *']
|
||||
)
|
||||
self.master.run_command(
|
||||
['ipa-acme-manage', 'pruning',
|
||||
'--certretention=30', '--certretentionunit=day']
|
||||
)
|
||||
self.master.run_command(
|
||||
['ipa-acme-manage', 'pruning',
|
||||
'--certsearchsizelimit=1000', '--certsearchtimelimit=0']
|
||||
)
|
||||
self.master.run_command(
|
||||
['ipa-acme-manage', 'pruning',
|
||||
'--requestretention=30', '--requestretentionunit=day']
|
||||
)
|
||||
self.master.run_command(
|
||||
['ipa-acme-manage', 'pruning',
|
||||
'--requestsearchsizelimit=1000', '--requestsearchtimelimit=0']
|
||||
)
|
||||
result = self.master.run_command(
|
||||
['ipa-acme-manage', 'pruning', '--config-show']
|
||||
)
|
||||
assert 'Status: enabled' in result.stdout_text
|
||||
assert 'Certificate Retention Time: 30' in result.stdout_text
|
||||
assert 'Certificate Retention Unit: day' in result.stdout_text
|
||||
assert 'Certificate Search Size Limit: 1000' in result.stdout_text
|
||||
assert 'Certificate Search Time Limit: 100' in result.stdout_text
|
||||
assert 'Request Retention Time: 30' in result.stdout_text
|
||||
assert 'Request Retention Unit: day' in result.stdout_text
|
||||
assert 'Request Search Size Limit' in result.stdout_text
|
||||
assert 'Request Search Time Limit: 100' in result.stdout_text
|
||||
assert 'cron Schedule: 0 0 1 * *' in result.stdout_text
|
||||
|
||||
def test_prune_disable(self, issue_and_expire_acme_cert):
|
||||
"""Test prune command throw error after disabling the pruning"""
|
||||
if (tasks.get_pki_version(self.master)
|
||||
< tasks.parse_version('11.3.0')):
|
||||
raise pytest.skip("Certificate pruning is not available")
|
||||
|
||||
self.master.run_command(['ipa-acme-manage', 'pruning', '--disable'])
|
||||
result = self.master.run_command(
|
||||
['ipa-acme-manage', 'pruning',
|
||||
'--cron=0 0 1 * *']
|
||||
)
|
||||
assert 'Status: disabled' in result.stdout_text
|
||||
|
Loading…
Reference in New Issue
Block a user