Skip to content

Commit d4388c7

Browse files
LDAP+Kerberos DNS SRV and ldap_sasl_canonicalize tests
Add and extend `LDAP_KRB5` for DNS SRV discovery and GSSAPI canonicalize behavior. | Test | Coverage | |------|----------| | `test_ldap_krb5__dns_srv_discovery_with_srv_uri` | `ldap_uri=_srv_`, `krb5_server=_srv_`; LDAP and Kerberos SRV resolved; SSH auth | | `test_ldap_krb5__kerberos_srv_discovery_with_ldap_uri_set` | BZ 700805 — Kerberos SRV when `ldap_uri` is explicit | | `test_ldap_krb5__dns_discovery_with_discovery_domain_set` | `dns_discovery_domain` with `ldap_uri` removed | | `test_ldap_krb5__ldap_sasl_canonicalize_handles_reverse_dns_mismatch` | BZ 732935 — bogus PTR + `ldap_sasl_canonicalize` with GSSAPI | Requires **sssd-test-framework** with: - `NetworkUtils.prepare_ldap_krb5_srv_discovery()` - `NetworkUtils.setup_sasl_canonicalize_bogus_ptr()` (resolves LDAP/KDC IPv4, returns addresses) - `NetworkUtils.dig()` / `has_srv_record()` - `LDAP.enable_gssapi()` - `GetentUtils.resolve_ipv4()` / `ahostsv4` Signed-off-by: Madhuri Upadhye <mupadhye@redhat.com>
1 parent 622fa7f commit d4388c7

2 files changed

Lines changed: 288 additions & 1 deletion

File tree

src/tests/system/requirements.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,5 @@ git+https://github.com/next-actions/pytest-mh
55
git+https://github.com/next-actions/pytest-ticket
66
git+https://github.com/next-actions/pytest-tier
77
git+https://github.com/next-actions/pytest-output
8-
git+https://github.com/SSSD/sssd-test-framework
8+
#git+https://github.com/SSSD/sssd-test-framework
9+
git+https://github.com/madhuriupadhye/sssd-test-framework@krb_misc2

src/tests/system/tests/test_ldap_krb5.py

Lines changed: 286 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,18 @@
1818
from sssd_test_framework.roles.client import Client
1919
from sssd_test_framework.roles.generic import GenericProvider
2020
from sssd_test_framework.roles.kdc import KDC
21+
from sssd_test_framework.roles.ldap import LDAP
2122
from sssd_test_framework.topology import KnownTopology
2223

24+
25+
def _assert_ldap_krb5_srv_records(client: Client, discovery_domain: str) -> None:
26+
for query in (
27+
f"_ldap._tcp.{discovery_domain}",
28+
f"_kerberos._udp.{discovery_domain}",
29+
):
30+
assert client.net.has_srv_record(query), f"No SRV record for {query}"
31+
32+
2333
NOBODY_C_SOURCE = (
2434
"#include <unistd.h>\n"
2535
"int main(void) {\n"
@@ -390,3 +400,279 @@ def test_ldap_krb5__password_change_via_ssh(client: Client, provider: GenericPro
390400
), f"krb5_child initial auth message not found: {log_content[:500]}!"
391401

392402
assert client.auth.ssh.password("puser1", new_password), "Auth with new password failed after password change!"
403+
404+
405+
@pytest.mark.importance("high")
406+
@pytest.mark.topology(KnownTopology.LDAP_KRB5)
407+
def test_ldap_krb5__dns_srv_discovery_with_srv_uri(client: Client, provider: GenericProvider, kdc: KDC):
408+
"""
409+
:title: DNS SRV discovery for LDAP using _srv_ URI
410+
:setup:
411+
1. Add user and configure SSSD with ldap_uri=_srv_, krb5_server=_srv_
412+
2. Restart SSSD
413+
:steps:
414+
1. Authenticate user via SSH
415+
2. Check logs for LDAP SRV resolution
416+
3. Check logs for LDAP SRV marked as resolved
417+
4. Check logs for Kerberos SRV resolution
418+
:expectedresults:
419+
1. Authentication succeeds
420+
2. Logs show LDAP SRV discovery attempt
421+
3. Logs show LDAP SRV marked as resolved
422+
4. Logs show Kerberos SRV marked as resolved
423+
:customerscenario: True
424+
"""
425+
discovery_domain = getattr(provider.host, "client", {}).get("dns_discovery_domain") or provider.domain
426+
client.net.prepare_ldap_krb5_srv_discovery(
427+
discovery_domain=discovery_domain,
428+
ldap_hostname=provider.host.hostname,
429+
kdc_hostname=kdc.host.hostname,
430+
client_hostname=client.host.hostname,
431+
)
432+
_assert_ldap_krb5_srv_records(client, discovery_domain)
433+
434+
a_result = client.net.dig(provider.host.hostname)
435+
assert a_result and any(
436+
r.get("type") == "A" for r in a_result
437+
), f"No A record for {provider.host.hostname}; LDAP host must be resolvable via DNS"
438+
439+
provider.user("puser1").add()
440+
kdc.principal("puser1").add()
441+
442+
client.authselect.select("sssd")
443+
client.sssd.common.krb5_auth(kdc)
444+
445+
client.sssd.domain["ldap_uri"] = "_srv_"
446+
client.sssd.domain["krb5_server"] = "_srv_"
447+
client.sssd.domain["dns_discovery_domain"] = discovery_domain
448+
client.sssd.domain["debug_level"] = "0xFFF0"
449+
450+
client.sssd.restart(clean=True)
451+
452+
assert client.tools.id("puser1"), "id failed for puser1 before SSH login"
453+
if not client.auth.ssh.password("puser1", "Secret123"):
454+
domain = client.sssd.default_domain
455+
krb_log = client.fs.read("/var/log/sssd/krb5_child.log")
456+
sssd_log = client.fs.read(f"/var/log/sssd/sssd_{domain}.log")
457+
raise AssertionError(
458+
"Authentication failed with DNS SRV discovery; "
459+
f"krb5_child.log tail: {krb_log[-1500:]!r}; "
460+
f"sssd_{domain}.log tail: {sssd_log[-1500:]!r}"
461+
)
462+
463+
domain = client.sssd.default_domain
464+
log_content = client.fs.read(f"/var/log/sssd/sssd_{domain}.log")
465+
466+
assert (
467+
f"Trying to resolve SRV record of '_ldap._tcp.{discovery_domain}'" in log_content
468+
or f"Trying to resolve SRV record of '_LDAP._tcp.{discovery_domain}'" in log_content
469+
), "LDAP SRV discovery attempt not found in logs!"
470+
471+
assert (
472+
"Marking SRV lookup of service 'LDAP' as 'resolved'" in log_content
473+
), "LDAP SRV lookup was not marked as resolved!"
474+
475+
assert (
476+
f"Trying to resolve SRV record of '_KERBEROS._udp.{discovery_domain}'" in log_content
477+
or f"Trying to resolve SRV record of '_kerberos._udp.{discovery_domain}'" in log_content
478+
), "Kerberos SRV discovery attempt not found in logs!"
479+
assert (
480+
"Marking SRV lookup of service 'KERBEROS' as 'resolved'" in log_content
481+
), "Kerberos SRV lookup was not marked as resolved!"
482+
483+
484+
@pytest.mark.importance("high")
485+
@pytest.mark.ticket(bz=700805)
486+
@pytest.mark.topology(KnownTopology.LDAP_KRB5)
487+
def test_ldap_krb5__kerberos_srv_discovery_with_ldap_uri_set(client: Client, provider: GenericProvider, kdc: KDC):
488+
"""
489+
:title: Kerberos DNS SRV discovery works when LDAP URI is set
490+
:setup:
491+
1. Add user and configure SSSD with explicit ldap_uri
492+
2. Restart SSSD
493+
:steps:
494+
1. Authenticate user via SSH
495+
2. Check logs for Kerberos SRV servers added
496+
3. Check logs for Kerberos SRV resolution attempt
497+
4. Verify no "unknown" errors in logs
498+
:expectedresults:
499+
1. Authentication succeeds
500+
2. Logs show Kerberos SRV for UDP and TCP
501+
3. Logs show Kerberos SRV resolution attempt
502+
4. No "unknown" errors in logs
503+
:customerscenario: True
504+
"""
505+
discovery_domain = getattr(provider.host, "client", {}).get("dns_discovery_domain") or provider.domain
506+
client.net.prepare_ldap_krb5_srv_discovery(
507+
discovery_domain=discovery_domain,
508+
ldap_hostname=provider.host.hostname,
509+
kdc_hostname=kdc.host.hostname,
510+
client_hostname=client.host.hostname,
511+
)
512+
_assert_ldap_krb5_srv_records(client, discovery_domain)
513+
514+
provider.user("puser1").add()
515+
kdc.principal("puser1").add()
516+
517+
client.sssd.common.krb5_auth(kdc)
518+
519+
# krb5_auth() sets krb5_server from mhc; use SRV discovery for Kerberos (BZ 700805).
520+
client.sssd.domain["krb5_server"] = "_srv_"
521+
client.sssd.domain["dns_discovery_domain"] = discovery_domain
522+
client.sssd.domain["dns_resolver_timeout"] = "60"
523+
client.sssd.domain["ldap_opt_timeout"] = "60"
524+
client.sssd.domain["debug_level"] = "0xFFF0"
525+
526+
client.sssd.restart(clean=True)
527+
528+
assert client.tools.id("puser1"), "id failed for puser1 before SSH login"
529+
if not client.auth.ssh.password("puser1", "Secret123"):
530+
domain = client.sssd.default_domain
531+
krb_log = client.fs.read("/var/log/sssd/krb5_child.log")
532+
sssd_log = client.fs.read(f"/var/log/sssd/sssd_{domain}.log")
533+
raise AssertionError(
534+
"Authentication failed; Kerberos SRV discovery should work even with "
535+
f"explicit ldap_uri; krb5_child.log tail: {krb_log[-1500:]!r}; "
536+
f"sssd_{domain}.log tail: {sssd_log[-1500:]!r}"
537+
)
538+
539+
domain = client.sssd.default_domain
540+
log_content = client.fs.read(f"/var/log/sssd/sssd_{domain}.log")
541+
542+
assert (
543+
"Adding new SRV server to service 'KERBEROS' using 'udp'" in log_content
544+
), "Kerberos SRV discovery (UDP) did not occur!"
545+
assert (
546+
"Adding new SRV server to service 'KERBEROS' using 'tcp'" in log_content
547+
), "Kerberos SRV discovery (TCP) did not occur!"
548+
549+
assert (
550+
f"Trying to resolve SRV record of '_KERBEROS._udp.{discovery_domain}'" in log_content
551+
or f"Trying to resolve SRV record of '_kerberos._udp.{discovery_domain}'" in log_content
552+
), "Kerberos SRV lookup attempt not found in logs!"
553+
554+
assert (
555+
"unknown" not in log_content.lower()
556+
), "BZ 700805 regression: 'unknown' error found in logs during DNS SRV discovery!"
557+
558+
559+
@pytest.mark.importance("high")
560+
@pytest.mark.topology(KnownTopology.LDAP_KRB5)
561+
def test_ldap_krb5__dns_discovery_with_discovery_domain_set(client: Client, provider: GenericProvider, kdc: KDC):
562+
"""
563+
:title: DNS SRV discovery uses dns_discovery_domain when explicitly set
564+
:setup:
565+
1. Ensure _ldap._tcp SRV for the provider domain and A record for LDAP host
566+
2. Add user and configure SSSD; remove ldap_uri; set dns_discovery_domain
567+
3. Restart SSSD
568+
:steps:
569+
1. Run id for puser1
570+
:expectedresults:
571+
1. User resolves; LDAP was reached via DNS SRV for the discovery domain
572+
:customerscenario: True
573+
"""
574+
discovery_domain = getattr(provider.host, "client", {}).get("dns_discovery_domain") or provider.domain
575+
client.net.prepare_ldap_krb5_srv_discovery(
576+
discovery_domain=discovery_domain,
577+
ldap_hostname=provider.host.hostname,
578+
kdc_hostname=kdc.host.hostname,
579+
client_hostname=client.host.hostname,
580+
)
581+
_assert_ldap_krb5_srv_records(client, discovery_domain)
582+
583+
a_result = client.net.dig(provider.host.hostname)
584+
assert a_result and any(
585+
r.get("type") == "A" for r in a_result
586+
), f"No A record for {provider.host.hostname}; LDAP host must be resolvable via DNS"
587+
588+
provider.user("puser1").add()
589+
kdc.principal("puser1").add()
590+
591+
client.sssd.common.krb5_auth(kdc)
592+
593+
if "ldap_uri" in client.sssd.domain:
594+
del client.sssd.domain["ldap_uri"]
595+
596+
client.sssd.domain["dns_discovery_domain"] = discovery_domain
597+
client.sssd.restart(clean=True)
598+
599+
result = client.tools.id("puser1")
600+
assert result is not None, "User lookup failed; LDAP DNS SRV discovery did not work"
601+
assert result.user.name == "puser1", f"Expected user puser1 but got {result.user.name}"
602+
603+
604+
@pytest.mark.importance("high")
605+
@pytest.mark.ticket(bz=732935)
606+
@pytest.mark.topology(KnownTopology.LDAP_KRB5)
607+
def test_ldap_krb5__ldap_sasl_canonicalize_handles_reverse_dns_mismatch(client: Client, provider: LDAP, kdc: KDC):
608+
"""
609+
:title: ldap_sasl_canonicalize handles reverse DNS mismatch with GSSAPI (BZ 732935)
610+
:setup:
611+
1. Resolve LDAP and KDC IPv4 on the client
612+
2. Configure bogus PTR for the LDAP IP (local named + hosts)
613+
3. Enable GSSAPI on LDAP server; add puser1 to LDAP and KDC
614+
4. Configure SSSD for LDAP+GSSAPI (hostname ldap_uri, rdns=false)
615+
:steps:
616+
1. Run getent passwd puser1 with hostname ldap_uri
617+
2. Run getent passwd puser1 with IPv4 ldap_uri and ldap_sasl_canonicalize=true
618+
3. Run getent passwd puser1 with ldap_sasl_canonicalize=false and hostname ldap_uri
619+
:expectedresults:
620+
1. User lookup succeeds without ldap_sasl_canonicalize
621+
2. User lookup fails when ldap_sasl_canonicalize=true and PTR does not match
622+
the Kerberos LDAP service hostname
623+
3. User lookup succeeds with ldap_sasl_canonicalize=false (workaround)
624+
:customerscenario: True
625+
"""
626+
ldap_ip, kdc_ip = client.net.setup_sasl_canonicalize_bogus_ptr(
627+
ldap_hostname=provider.host.hostname,
628+
ldap_host=provider.host,
629+
kdc_hostname=kdc.host.hostname,
630+
kdc_host=kdc.host,
631+
provider_domain=provider.domain,
632+
client_hostname=client.host.hostname,
633+
)
634+
635+
provider.enable_gssapi(kdc)
636+
637+
provider.user("puser1").add(uid=50001, gid=50001, password="12345678")
638+
kdc.principal("puser1").add(password="12345678")
639+
640+
client.sssd.common.krb5_auth(kdc)
641+
client.sssd.domain["ldap_sasl_mech"] = "GSSAPI"
642+
client.sssd.domain["ldap_sasl_authid"] = f"host/{client.host.hostname}"
643+
ldap_hostname_uri = f"ldap://{provider.host.hostname}"
644+
client.sssd.domain["ldap_uri"] = ldap_hostname_uri
645+
for tls_opt in ("ldap_tls_cacert", "ldap_tls_reqcert", "ldap_id_use_start_tls"):
646+
if tls_opt in provider.host.client:
647+
client.sssd.domain[tls_opt] = provider.host.client[tls_opt]
648+
client.sssd.domain["lookup_family_order"] = "ipv4_first"
649+
client.sssd.domain["krb5_canonicalize"] = "false"
650+
client.sssd.domain["debug_level"] = "0xFFF0"
651+
652+
client.sssd.restart(clean=True)
653+
result_baseline = client.tools.getent.passwd("puser1")
654+
assert result_baseline is not None, "getent passwd puser1 must succeed without ldap_sasl_canonicalize"
655+
656+
client.sssd.domain["ldap_uri"] = f"ldap://{ldap_ip}"
657+
client.sssd.domain["ldap_id_use_start_tls"] = "false"
658+
client.sssd.domain["ldap_sasl_canonicalize"] = "true"
659+
client.sssd.restart(clean=True)
660+
661+
result_with_canonicalize = client.tools.getent.passwd("puser1")
662+
assert result_with_canonicalize is None, (
663+
"getent passwd puser1 must fail with ldap_uri as IPv4 and "
664+
"ldap_sasl_canonicalize=true when reverse DNS PTR does not match "
665+
"the Kerberos LDAP service hostname (BZ 732935)"
666+
)
667+
668+
client.sssd.domain["ldap_uri"] = ldap_hostname_uri
669+
for tls_opt in ("ldap_tls_cacert", "ldap_tls_reqcert", "ldap_id_use_start_tls"):
670+
if tls_opt in provider.host.client:
671+
client.sssd.domain[tls_opt] = provider.host.client[tls_opt]
672+
client.sssd.domain["ldap_sasl_canonicalize"] = "false"
673+
client.sssd.restart(clean=True)
674+
675+
result_with_fix = client.tools.getent.passwd("puser1")
676+
assert result_with_fix is not None, (
677+
"getent passwd puser1 must succeed with ldap_sasl_canonicalize=false " "while bogus PTR remains in place"
678+
)

0 commit comments

Comments
 (0)