mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-01-16 11:21:56 -06:00
9e0084ba98
0d67180f7d
introduced the with_admin
fixture using class scope, which caused test failures as pytest
instantiated it before the multihost fixture.
It additionally failed to account for jitter - the issued ticket becomes
within a window of the expected lifetime, so we need to include the
ticket lifetime jitter into that calculation.
Finally, the PKINIT test could not have ever worked because PKINIT is
not set up as part of policy testing.
Related: https://pagure.io/freeipa/issue/8590
Also-authored-by: Rob Crittenden <rcritten@redhat.com>
Signed-off-by: Robbie Harwood <rharwood@redhat.com>
Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
191 lines
7.4 KiB
Python
191 lines
7.4 KiB
Python
#
|
|
# Copyright (C) 2019,2020 FreeIPA Contributors see COPYING for license
|
|
#
|
|
|
|
"""
|
|
Module provides tests for Kerberos ticket policy options
|
|
"""
|
|
|
|
from __future__ import absolute_import
|
|
|
|
import pytest
|
|
import time
|
|
from datetime import datetime
|
|
|
|
from ipatests.test_integration.base import IntegrationTest
|
|
from ipatests.test_integration.test_otp import add_otptoken, del_otptoken
|
|
from ipatests.pytest_ipa.integration import tasks
|
|
|
|
PASSWORD = "Secret123"
|
|
USER1 = "testuser1"
|
|
USER2 = "testuser2"
|
|
MAXLIFE = 86400
|
|
|
|
|
|
def maxlife_within_policy(input, maxlife, slush=3600):
|
|
"""Given klist output of the TGT verify that it is within policy
|
|
|
|
Ensure that the validity period is somewhere within the
|
|
absolute maxlife and a slush value, maxlife - slush.
|
|
|
|
Returns True if within policy.
|
|
|
|
Input should be a string like:
|
|
11/19/2019 16:37:40 11/20/2019 16:37:39 krbtgt/...
|
|
|
|
slush defaults to 1 * 60 * 60 matching the jitter window.
|
|
"""
|
|
data = input.split()
|
|
start = datetime.strptime(data[0] + ' ' + data[1], '%m/%d/%Y %H:%M:%S')
|
|
end = datetime.strptime(data[2] + ' ' + data[3], '%m/%d/%Y %H:%M:%S')
|
|
diff = int((end - start).total_seconds())
|
|
|
|
return maxlife >= diff >= maxlife - slush
|
|
|
|
|
|
def reset_to_default_policy(host, user):
|
|
"""Reset default user authentication and user authentication type"""
|
|
tasks.kinit_admin(host)
|
|
host.run_command(['ipa', 'user-mod', user, '--user-auth-type='])
|
|
host.run_command(['ipa', 'krbtpolicy-reset', user])
|
|
|
|
|
|
def kinit_check_life(master, user):
|
|
"""Acquire a TGT and check if it's within the lifetime window"""
|
|
master.run_command(["kinit", user], stdin_text=f"{PASSWORD}\n")
|
|
result = master.run_command("klist | grep krbtgt")
|
|
assert maxlife_within_policy(result.stdout_text, MAXLIFE) is True
|
|
|
|
|
|
class TestPWPolicy(IntegrationTest):
|
|
"""Tests password custom and default password policies.
|
|
"""
|
|
num_replicas = 0
|
|
|
|
@classmethod
|
|
def install(cls, mh):
|
|
tasks.install_master(cls.master)
|
|
tasks.create_active_user(cls.master, USER1, PASSWORD)
|
|
tasks.create_active_user(cls.master, USER2, PASSWORD)
|
|
|
|
@pytest.fixture(autouse=True, scope="function")
|
|
def with_admin(self):
|
|
tasks.kinit_admin(self.master)
|
|
yield
|
|
tasks.kdestroy_all(self.master)
|
|
|
|
def test_krbtpolicy_default(self):
|
|
"""Test the default kerberos ticket policy 24-hr tickets"""
|
|
master = self.master
|
|
master.run_command(['ipa', 'krbtpolicy-mod', USER1,
|
|
'--maxlife', str(MAXLIFE)])
|
|
tasks.kdestroy_all(master)
|
|
|
|
master.run_command(['kinit', USER1],
|
|
stdin_text=PASSWORD + '\n')
|
|
result = master.run_command('klist | grep krbtgt')
|
|
assert maxlife_within_policy(result.stdout_text, MAXLIFE) is True
|
|
|
|
def test_krbtpolicy_hardended(self):
|
|
"""Test a hardened kerberos ticket policy with 10 min tickets"""
|
|
master = self.master
|
|
master.run_command(['ipa', 'user-mod', USER1,
|
|
'--user-auth-type', 'password',
|
|
'--user-auth-type', 'hardened'])
|
|
master.run_command(['ipa', 'config-mod',
|
|
'--user-auth-type', 'password',
|
|
'--user-auth-type', 'hardened'])
|
|
master.run_command(['ipa', 'krbtpolicy-mod', USER1,
|
|
'--hardened-maxlife', '600'])
|
|
|
|
tasks.kdestroy_all(master)
|
|
|
|
master.run_command(['kinit', USER1],
|
|
stdin_text=PASSWORD + '\n')
|
|
result = master.run_command('klist | grep krbtgt')
|
|
assert maxlife_within_policy(result.stdout_text, 600,
|
|
slush=600) is True
|
|
|
|
tasks.kdestroy_all(master)
|
|
|
|
# Verify that the short policy only applies to USER1
|
|
master.run_command(['kinit', USER2],
|
|
stdin_text=PASSWORD + '\n')
|
|
result = master.run_command('klist | grep krbtgt')
|
|
assert maxlife_within_policy(result.stdout_text, MAXLIFE) is True
|
|
|
|
def test_krbtpolicy_password(self):
|
|
"""Test the kerberos ticket policy which issues 20 min tickets"""
|
|
master = self.master
|
|
master.run_command(['ipa', 'krbtpolicy-mod', USER2,
|
|
'--maxlife', '1200'])
|
|
|
|
tasks.kdestroy_all(master)
|
|
|
|
master.run_command(['kinit', USER2],
|
|
stdin_text=PASSWORD + '\n')
|
|
result = master.run_command('klist | grep krbtgt')
|
|
assert maxlife_within_policy(result.stdout_text, 1200,
|
|
slush=1200) is True
|
|
|
|
def test_krbtpolicy_reset(self):
|
|
"""Test a hardened kerberos ticket policy reset"""
|
|
master = self.master
|
|
master.run_command(['ipa', 'krbtpolicy-reset', USER2])
|
|
master.run_command(['kinit', USER2],
|
|
stdin_text=PASSWORD + '\n')
|
|
result = master.run_command('klist | grep krbtgt')
|
|
assert maxlife_within_policy(result.stdout_text, MAXLIFE) is True
|
|
|
|
def test_krbtpolicy_otp(self):
|
|
"""Test otp ticket policy"""
|
|
master = self.master
|
|
master.run_command(['ipa', 'user-mod', USER1,
|
|
'--user-auth-type', 'otp'])
|
|
master.run_command(['ipa', 'config-mod',
|
|
'--user-auth-type', 'otp'])
|
|
master.run_command(['ipa', 'krbtpolicy-mod', USER1,
|
|
'--otp-maxrenew=90', '--otp-maxlife=60'])
|
|
armor = tasks.create_temp_file(self.master, create_file=False)
|
|
otpuid, totp = add_otptoken(master, USER1, otptype="totp")
|
|
otpvalue = totp.generate(int(time.time())).decode("ascii")
|
|
try:
|
|
tasks.kdestroy_all(master)
|
|
# create armor for FAST
|
|
master.run_command(['kinit', '-n', '-c', armor])
|
|
# expect ticket expire in otp-maxlife=60 seconds
|
|
master.run_command(
|
|
['kinit', '-T', armor, USER1, '-r', '90'],
|
|
stdin_text='{0}{1}\n'.format(PASSWORD, otpvalue))
|
|
master.run_command(['ipa', 'user-find', USER1])
|
|
time.sleep(30)
|
|
# when user kerberos ticket expired but still within renew time,
|
|
# kinit -R should give user new life
|
|
master.run_command(['kinit', '-R', USER1])
|
|
master.run_command(['ipa', 'user-find', USER1])
|
|
time.sleep(60)
|
|
# when renew time expires, kinit -R should fail
|
|
result1 = master.run_command(['kinit', '-R', USER1],
|
|
raiseonerr=False)
|
|
tasks.assert_error(
|
|
result1,
|
|
"kinit: Ticket expired while renewing credentials", 1)
|
|
master.run_command(['ipa', 'user-find', USER1],
|
|
ok_returncode=1)
|
|
finally:
|
|
del_otptoken(master, otpuid)
|
|
reset_to_default_policy(master, USER1)
|
|
self.master.run_command(['rm', '-f', armor])
|
|
master.run_command(['ipa', 'config-mod', '--user-auth-type='])
|
|
|
|
def test_krbtpolicy_jitter(self):
|
|
"""Test jitter lifetime with no auth indicators"""
|
|
kinit_check_life(self.master, USER1)
|
|
|
|
def test_krbtpolicy_jitter_otp(self):
|
|
"""Test jitter lifetime with OTP"""
|
|
self.master.run_command(["ipa", "user-mod", USER1,
|
|
"--user-auth-type", "otp"])
|
|
kinit_check_life(self.master, USER1)
|
|
reset_to_default_policy(self.master, USER1)
|