Skip to content

tests: port LDAP+Kerberos tests to pytest#8544

Open
madhuriupadhye wants to merge 1 commit intoSSSD:masterfrom
madhuriupadhye:ldap_krb1
Open

tests: port LDAP+Kerberos tests to pytest#8544
madhuriupadhye wants to merge 1 commit intoSSSD:masterfrom
madhuriupadhye:ldap_krb1

Conversation

@madhuriupadhye
Copy link
Copy Markdown
Contributor

  • 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

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment on lines +106 to +109
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,
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

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}!"

@madhuriupadhye
Copy link
Copy Markdown
Contributor Author

/gemini review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.txt where 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...finally blocks 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
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

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.

Comment on lines +104 to +109
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,
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

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.

: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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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(
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

download()/upload()?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated.

@madhuriupadhye madhuriupadhye force-pushed the ldap_krb1 branch 2 times, most recently from 68ae3d4 to dc51504 Compare March 30, 2026 14:05
@madhuriupadhye madhuriupadhye requested a review from thalman March 31, 2026 10:19
Copy link
Copy Markdown
Contributor

@thalman thalman left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
@@ -0,0 +1,283 @@
"""
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You shouldn't need to restore the context.

"""
:title: Kerberos errors (clock skew) are logged to syslog
:setup:
1. Ensure chronyc is available
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this is the only inline comment that improves comprehension of the test; I'd remove the others.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants