tests: port LDAP+Kerberos tests to pytest#8544
tests: port LDAP+Kerberos tests to pytest#8544madhuriupadhye wants to merge 1 commit intoSSSD:masterfrom
Conversation
madhuriupadhye
commented
Mar 23, 2026
- Port three downstream krb_misc_bugzilla bash tests to upstream pytest
- BZ 773660: Clock skew errors logged to syslog
- BZ 869150: ldap_child handles missing keytab without segfault
- BZ 805281: Correct principal selected from multi-realm keytab
There was a problem hiding this comment.
Code Review
This pull request ports three bash tests for LDAP+Kerberos to pytest. The new tests are well-structured and cover important scenarios like clock skew handling, missing keytabs, and multi-realm principal selection. My review focuses on improving the robustness of the clock skew test by removing a hardcoded external dependency, which will make the test more reliable.
| client.host.conn.run( | ||
| "systemctl stop chronyd 2>/dev/null; chronyd -q 'server clock.redhat.com iburst' 2>/dev/null; systemctl start chronyd 2>/dev/null || true", | ||
| raise_on_error=False, | ||
| ) |
There was a problem hiding this comment.
The command to sync NTP is overly complex, suppresses errors, and relies on a hardcoded external server (clock.redhat.com). This can make the test flaky and hard to debug. A more robust approach is to use chronyc to trigger an immediate clock step with the configured NTP servers.
# Sync chrony to NTP
result = client.host.conn.run("chronyc -a makestep", raise_on_error=False)
assert "200 OK" in result.stdout or result.rc == 0, f"chrony makestep failed: {result.stderr}!"5e56975 to
83e1b5d
Compare
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request ports three LDAP+Kerberos tests from bash to pytest, which is a great improvement for maintainability. The new tests are well-structured and cover important bug-fix scenarios.
My review has identified a few issues that should be addressed:
- A critical issue in
requirements.txtwhere a dependency points to a personal fork. This must be changed to an official repository before merging. - The tests have some reliability concerns. One test depends on a hardcoded external NTP server, which can cause flakiness.
- Two tests lack robust resource cleanup (for keytab files). If a test fails, it could leave the system in a modified state and affect subsequent test runs. I've suggested using
try...finallyblocks to ensure cleanup always happens.
Addressing these points will improve the reliability and maintainability of the new tests.
| git+https://github.com/next-actions/pytest-tier | ||
| git+https://github.com/next-actions/pytest-output | ||
| git+https://github.com/SSSD/sssd-test-framework | ||
| git+https://github.com/madhuriupadhye/sssd-test-framework@krb_misc |
There was a problem hiding this comment.
The sssd-test-framework dependency points to a personal fork (madhuriupadhye/sssd-test-framework@krb_misc). This introduces a significant risk as personal forks may not be stable, maintained, or accessible in the long term. Before merging, this should be changed to point to the official repository, preferably a specific tag or commit hash from the main project to ensure reproducible builds.
| client.host.conn.run( | ||
| "systemctl stop chronyd 2>/dev/null;" | ||
| " chronyd -q 'server clock.redhat.com iburst' 2>/dev/null;" | ||
| " systemctl start chronyd 2>/dev/null || true", | ||
| raise_on_error=False, | ||
| ) |
There was a problem hiding this comment.
The test hardcodes an external NTP server clock.redhat.com. This creates a dependency on an external service and network connectivity, which can lead to flaky tests. It's recommended to use an NTP server provided by the test infrastructure or a more generic pool address if one must be used. If possible, abstract this into a configurable variable.
45f0377 to
812552e
Compare
| :setup: | ||
| 1. Add user puser1 to LDAP and KDC | ||
| 2. Configure SSSD with LDAP-KRB5, ldap_sasl_mech=GSSAPI | ||
| 3. Move /etc/krb5.keytab to /etc/krb5.keytab.moved |
There was a problem hiding this comment.
Sorry I do not get this test. What I see is
- create keytab file (on kdc)
- download it
- upload it to he other host
- rename it so it does not matches config and therefore is not used
Why we bother with this file if it is not used at all?
Also you say here it is /etc/krb5.keytab but then you use variable keytab_path set to /tmp/ldap_test.keytab.
There was a problem hiding this comment.
The test creates a keytab at /tmp/ldap_test.keytab, configures SSSD to use it via ldap_krb5_keytab, then moves it away. The docstring said /etc/krb5.keytab which was wrong — updated the docstring to match keytab_path. Also add a comment explaining: we create a valid keytab first so SSSD config is correct, then remove it to test the crash path.
| git+https://github.com/next-actions/pytest-tier | ||
| git+https://github.com/next-actions/pytest-output | ||
| git+https://github.com/SSSD/sssd-test-framework | ||
| git+https://github.com/madhuriupadhye/sssd-test-framework@krb_misc |
There was a problem hiding this comment.
This must be reverted before merging IMO.
| pytest.skip(f"ktutil failed to create mixed keytab: {result.stderr or result.stdout}") | ||
|
|
||
| # Backup and install mixed keytab | ||
| client.host.conn.run( |
There was a problem hiding this comment.
I do not see any restore for this backup. Why not simply remove it with utils.fs.rm() - it should take care for restore if that file exists.
There was a problem hiding this comment.
Used client.fs.rm("/etc/krb5.keytab") instead of manual backup/restore — the framework handles auto-restore.
| host_principal = f"host/{client.host.hostname}" | ||
| kdc.principal(host_principal).add(password=None) | ||
| kdc.kadmin(f"ktadd -k {keytab_path} {host_principal}") | ||
| result = client.host.conn.run( |
There was a problem hiding this comment.
Did you consider using fs.download() / fs.upload()? That would be much cleaner with regard of getting the environment into original state when the test finishes.
There was a problem hiding this comment.
Replace the raw scp commands with framework's client.fs.download() / kdc.fs.upload() for keytab transfer between hosts.
| host_principal = f"host/{client.host.hostname}" | ||
| kdc.principal(host_principal).add(password=None) | ||
| kdc.kadmin(f"ktadd -k {valid_keytab} {host_principal}") | ||
| result = client.host.conn.run( |
68ae3d4 to
dc51504
Compare
thalman
left a comment
There was a problem hiding this comment.
LGTM, thanks
We just have to wait for requirements.txt not to point to personal repo
- Port three downstream krb_misc_bugzilla bash tests to upstream pytest - BZ 773660: Clock skew errors logged to syslog - BZ 869150: ldap_child handles missing keytab without segfault - BZ 805281: Correct principal selected from multi-realm keytab Signed-off-by: Madhuri Upadhye <mupadhye@redhat.com>
dc51504 to
59a0f4e
Compare
| @@ -0,0 +1,283 @@ | |||
| """ | |||
There was a problem hiding this comment.
I think this file, should match the provider name, so test_ldap_krb5.py
| """ | ||
| SSSD krb misc bugzilla tests. | ||
|
|
||
| Port of sssd-qe client/krb_provider/krb_misc_bugzilla tests. |
There was a problem hiding this comment.
Not a port, it's a rewrite. I don't think we need to reference where these tests came from.
SSSD LDAP/KRB5 Tests.
Tests where the 'id_provider` is set to 'ldap' and the `auth_provider` is set to 'krb5'.
| # Configure SSSD with LDAP+KRB5, chpass_provider=krb5 | ||
| client.sssd.common.krb5_auth(kdc) | ||
| client.sssd.domain["chpass_provider"] = "krb5" | ||
| client.sssd.domain["enumerate"] = "true" |
There was a problem hiding this comment.
I don't think enumerate is required. Can you check? If it's not, let's remove it so we minimize the extra configuration parameters.
| "forwardable = yes\nkdc_timesync = 0", | ||
| ) | ||
| client.fs.write("/etc/krb5.conf", krb5_conf) | ||
| client.host.conn.run("restorecon -v /etc/krb5.conf", raise_on_error=False) |
There was a problem hiding this comment.
You shouldn't need to restore the context.
| """ | ||
| :title: Kerberos errors (clock skew) are logged to syslog | ||
| :setup: | ||
| 1. Ensure chronyc is available |
There was a problem hiding this comment.
I would simplify/combine the docstring steps to something like this.
:title: Clock skew errors are logged to syslog.
This rest requires 'chronyc'; the test will skip if missing.
:setup:
1. Create user and kerberos principal
2. Configure SSSD
3. Disable time sync and start SSSD
:step:
1. Login as user
2. Change the system time to be one day ahead
3. Login again
4. Check the logs
:expectedresults:
1. Login successful
2. System time has changed
3. Login fails
4. Logs contain a time skew message
Please do something similar with the next tests as well. Remember, docstrings should summarize and explain the scope of the test; the details are in the code.
| pytest.skip(f"chronyd not running or chrony manual mode failed: {result.stdout}") | ||
|
|
||
| try: | ||
| # Move system time forward (+1 day) to cause clock skew |
There was a problem hiding this comment.
Not part of this PR, but we should see how many tests require the time to be incorrect. I think quite a few, so this would be a nice addition to the framework.
| auth_ok = client.auth.ssh.password("a1m2user", "Secret123") | ||
| assert not auth_ok, "Auth should fail due to clock skew!" | ||
| finally: | ||
| # Always restore time even if asserts fail |
There was a problem hiding this comment.
I find this is the only inline comment that improves comprehension of the test; I'd remove the others.