Skip to content

Commit 4248db6

Browse files
Test: changes for krb_misc
Signed-off-by: Madhuri Upadhye <mupadhye@redhat.com>
1 parent 8a9e9d9 commit 4248db6

4 files changed

Lines changed: 175 additions & 3 deletions

File tree

sssd_test_framework/roles/client.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from ..topology import SSSDTopologyMark
99
from ..utils.adcli import AdcliUtils
1010
from ..utils.automount import AutomountUtils
11+
from ..utils.krb5 import Krb5KeytabUtils
1112
from ..utils.gdm import GDM
1213
from ..utils.ldb import LDBUtils
1314
from ..utils.local_users import LocalGroup, LocalSudoRule, LocalUser, LocalUsersUtils
@@ -110,6 +111,12 @@ def __init__(self, *args, **kwargs) -> None:
110111
Managing virtual passkey device and service
111112
"""
112113

114+
self.krb5: Krb5KeytabUtils = Krb5KeytabUtils(self.host)
115+
"""
116+
Kerberos keytab utilities (ktutil via expect).
117+
"""
118+
119+
113120
def setup(self) -> None:
114121
"""
115122
Called before execution of each test.

sssd_test_framework/roles/kdc.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,21 +163,38 @@ def __init__(self, role: KDC, name: str) -> None:
163163
self.name: str = name
164164
"""Principal name."""
165165

166-
def add(self, *, password: str | None = "Secret123") -> KDCPrincipal:
166+
def add(
167+
self,
168+
*,
169+
password: str | None = "Secret123",
170+
requires_preauth: bool = False,
171+
extra_options: str | None = None,
172+
) -> KDCPrincipal:
167173
"""
168174
Add a new Kerberos principal.
169175
170176
Random password is generated if ``password`` is ``None``.
171177
172178
:param password: Principal's password, defaults to 'Secret123'
173179
:type password: str | None
180+
:param requires_preauth: Add +requires_preauth flag (for clock skew tests), defaults to False
181+
:type requires_preauth: bool, optional
182+
:param extra_options: Extra addprinc options (e.g. '+nokey'), defaults to None
183+
:type extra_options: str | None, optional
174184
:return: Self.
175185
:rtype: KDCPrincipal
176186
"""
187+
opts: list[str] = []
188+
if requires_preauth:
189+
opts.append("+requires_preauth")
190+
if extra_options:
191+
opts.append(extra_options)
192+
opts_str = " " + " ".join(opts) if opts else ""
193+
177194
if password is not None:
178-
self.role.kadmin(f'addprinc -pw "{password}" "{self.name}"')
195+
self.role.kadmin(f'addprinc -pw "{password}"{opts_str} "{self.name}"')
179196
else:
180-
self.role.kadmin(f'addprinc -randkey "{self.name}"')
197+
self.role.kadmin(f'addprinc -randkey{opts_str} "{self.name}"')
181198

182199
return self
183200

sssd_test_framework/utils/authentication.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1597,3 +1597,56 @@ def password(self, user: str, password: str, new_password: str, retyped: str | N
15971597
raise ExpectScriptError(result.rc)
15981598

15991599
return result.rc == 0
1600+
1601+
def password_via_ssh(
1602+
self,
1603+
user: str,
1604+
password: str,
1605+
new_password: str,
1606+
retyped: str | None = None,
1607+
*,
1608+
host: str = "localhost",
1609+
raise_on_error: bool = True,
1610+
) -> bool:
1611+
"""
1612+
Change password via SSH session (port of sssd-qe expect script).
1613+
1614+
SSHs as user, runs passwd interactively, and changes password.
1615+
Used when testing krb5_child "Initial authentication for change password".
1616+
1617+
:param user: Username.
1618+
:param password: Current password.
1619+
:param new_password: New password.
1620+
:param retyped: Retyped new password (defaults to new_password).
1621+
:param host: SSH target host, defaults to "localhost".
1622+
:param raise_on_error: Raise ExpectScriptError on failure.
1623+
:return: True if password change succeeded.
1624+
"""
1625+
if retyped is None:
1626+
retyped = new_password
1627+
1628+
result = self.host.conn.expect(
1629+
rf"""
1630+
set timeout {DEFAULT_AUTHENTICATION_TIMEOUT}
1631+
spawn ssh -o StrictHostKeyChecking=no -l {user} {host}
1632+
expect -nocase "*password:"
1633+
send "{password}\r"
1634+
sleep 5
1635+
send "passwd\r"
1636+
expect -nocase "*Current Password:"
1637+
send "{password}\r"
1638+
expect -nocase "New password:"
1639+
send "{new_password}\r"
1640+
expect -nocase "Retype new password:"
1641+
send "{retyped}\r"
1642+
expect -re "passwd: .+ updated successfully"
1643+
send "exit\r"
1644+
expect eof
1645+
""",
1646+
raise_on_error=raise_on_error,
1647+
)
1648+
1649+
if raise_on_error and result.rc > 200:
1650+
raise ExpectScriptError(result.rc)
1651+
1652+
return result.rc == 0

sssd_test_framework/utils/krb5.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
"""Kerberos and keytab utilities."""
2+
3+
from __future__ import annotations
4+
5+
from pytest_mh import MultihostHost, MultihostUtility
6+
from pytest_mh.conn import ProcessResult
7+
8+
__all__ = [
9+
"Krb5KeytabUtils",
10+
]
11+
12+
13+
class Krb5KeytabUtils(MultihostUtility[MultihostHost]):
14+
"""
15+
Keytab manipulation via ktutil (expect-based).
16+
17+
Port of expect scripts from sssd-qe client/krb_provider/krb_misc_bugzilla.
18+
"""
19+
20+
def ktutil_create_mixed_keytab(
21+
self,
22+
wrong_principal: str,
23+
valid_keytab: str,
24+
output_keytab: str,
25+
password: str = "Secret123",
26+
*,
27+
raise_on_error: bool = True,
28+
) -> ProcessResult:
29+
"""
30+
Create keytab with wrong principal first, then entries from valid keytab.
31+
32+
BZ 805281: Uses ktutil to add a password-based entry (wrong realm) first,
33+
then merge with an existing keytab. Tests that SSSD selects the correct
34+
principal when multiple realms exist in one keytab.
35+
36+
:param wrong_principal: Principal to add first (e.g. nfs/host@TEST.EXAMPLE.COM)
37+
:param valid_keytab: Path to keytab with correct principal
38+
:param output_keytab: Path for the combined keytab output
39+
:param password: Password for addent -password, defaults to "Secret123"
40+
:param raise_on_error: Raise on failure, defaults to True
41+
:return: Process result from expect
42+
"""
43+
return self.host.conn.expect(
44+
f"""
45+
spawn ktutil
46+
expect "ktutil: "
47+
send "addent -password -p {wrong_principal} -k 3 -e rc4-hmac\\r"
48+
expect "Password: *"
49+
send "{password}\\r"
50+
send "rkt {valid_keytab}\\r"
51+
send "wkt {output_keytab}\\r"
52+
expect eof
53+
""",
54+
raise_on_error=raise_on_error,
55+
)
56+
57+
def ktutil_create_keytab(
58+
self,
59+
principal: str,
60+
output_keytab: str,
61+
password: str = "Secret123",
62+
enctype: str = "aes256-cts-hmac-sha1-96",
63+
kvno: int = 1,
64+
*,
65+
raise_on_error: bool = True,
66+
) -> ProcessResult:
67+
"""
68+
Create keytab with single password-based entry (BZ 1198478).
69+
70+
Uses ktutil to add a principal with password and write to keytab file.
71+
Useful for dummy keytabs (principal in keytab but not on KDC).
72+
73+
:param principal: Principal name (e.g. bla@EXAMPLE.COM)
74+
:param output_keytab: Path for the keytab output
75+
:param password: Password for addent -password, defaults to "Secret123"
76+
:param enctype: Encryption type (default: aes256-cts-hmac-sha1-96)
77+
:param kvno: Key version number, defaults to 1
78+
:param raise_on_error: Raise on failure, defaults to True
79+
:return: Process result from expect
80+
"""
81+
return self.host.conn.expect(
82+
f"""
83+
spawn ktutil
84+
expect "ktutil: "
85+
send "addent -password -p {principal} -k {kvno} -e {enctype}\\r"
86+
expect "Password: *"
87+
send "{password}\\r"
88+
expect "ktutil: "
89+
send "wkt {output_keytab}\\r"
90+
expect "ktutil: "
91+
send "q\\r"
92+
expect eof
93+
""",
94+
raise_on_error=raise_on_error,
95+
)

0 commit comments

Comments
 (0)