|
7 | 7 | from __future__ import annotations |
8 | 8 |
|
9 | 9 | import re |
| 10 | +import textwrap |
| 11 | +from inspect import cleandoc |
10 | 12 |
|
11 | 13 | import pytest |
12 | 14 | from sssd_test_framework.roles.client import Client |
13 | 15 | from sssd_test_framework.roles.generic import GenericProvider |
| 16 | +from sssd_test_framework.roles.ipa import IPA |
14 | 17 | from sssd_test_framework.roles.kdc import KDC |
| 18 | +from sssd_test_framework.roles.samba import Samba |
15 | 19 | from sssd_test_framework.topology import KnownTopology, KnownTopologyGroup |
16 | 20 |
|
17 | 21 |
|
@@ -375,3 +379,142 @@ def test_ensure_localauth_plugin_is_not_configured(client: Client, provider: Gen |
375 | 379 |
|
376 | 380 | with pytest.raises(Exception): |
377 | 381 | client.fs.read("/var/lib/sss/pubconf/krb5.include.d/localauth_plugin") |
| 382 | + |
| 383 | + |
| 384 | +@pytest.mark.importance("medium") |
| 385 | +@pytest.mark.topology(KnownTopologyGroup.AnyProvider) |
| 386 | +@pytest.mark.parametrize( |
| 387 | + "prompting_section", |
| 388 | + ["prompting/password", "prompting/password/su-l"], |
| 389 | + ids=["global_prompt", "service_prompt"], |
| 390 | +) |
| 391 | +def test_authentication__custom_password_prompt_is_shown_at_login( |
| 392 | + client: Client, provider: GenericProvider, prompting_section: str |
| 393 | +): |
| 394 | + """ |
| 395 | + :title: Custom password prompt text is shown at login |
| 396 | + :description: |
| 397 | + 'su -' uses the 'su-l' PAM service, so the per-service case targets |
| 398 | + '[prompting/password/su-l]', not '[prompting/password/su]'. |
| 399 | + :setup: |
| 400 | + 1. Create user |
| 401 | + 2. Set a custom 'password_prompt', either globally or for the 'su -' PAM service ('su-l') |
| 402 | + 3. Start SSSD |
| 403 | + :steps: |
| 404 | + 1. Authenticate as the user via 'su -' |
| 405 | + :expectedresults: |
| 406 | + 1. The custom prompt text is shown and authentication succeeds |
| 407 | + :customerscenario: True |
| 408 | + """ |
| 409 | + provider.user("user1").add(password="Secret123") |
| 410 | + client.sssd.section(prompting_section)["password_prompt"] = "My custom prompt" |
| 411 | + client.sssd.start() |
| 412 | + |
| 413 | + result = client.host.conn.run("su - user1 -c 'su - user1 -c whoami'", input="Secret123") |
| 414 | + assert "My custom prompt" in result.stderr, "Custom password prompt was not shown!" |
| 415 | + assert "user1" in result.stdout, "'user1' failed to log in!" |
| 416 | + |
| 417 | + |
| 418 | +@pytest.mark.importance("medium") |
| 419 | +@pytest.mark.authentication |
| 420 | +@pytest.mark.topology(KnownTopology.ALLDC) |
| 421 | +def test_authentication__pam_sss_domains_skips_non_matching_krb5_domains( |
| 422 | + client: Client, samba: Samba, ipa: IPA, kdc: KDC |
| 423 | +): |
| 424 | + """ |
| 425 | + :title: pam_sss.so 'domains' authenticates only against the listed Kerberos realm domain |
| 426 | + :description: |
| 427 | + Local users may authenticate via Kerberos against one of several configured realms |
| 428 | + (Samba, IPA, or a standalone KDC). The same username exists in every realm with a |
| 429 | + different password; each PAM 'domains=' line ignores the other realms and only tries |
| 430 | + its listed domain. |
| 431 | + :setup: |
| 432 | + 1. Add a local user and create 'user1' in the Samba, IPA, and KDC realms with |
| 433 | + different passwords |
| 434 | + 2. Configure three SSSD domains (samba, ipa, krb5) with id_provider=proxy/files and |
| 435 | + auth_provider=krb5 using each provider's realm |
| 436 | + 3. Replace 'su-l' with three 'sufficient' pam_sss.so lines, each limited by 'domains=' |
| 437 | + :steps: |
| 438 | + 1. Authenticate as the local user via 'su -' using the KDC password |
| 439 | + 2. Change the IPA principal's password to match the KDC password and authenticate again |
| 440 | + :expectedresults: |
| 441 | + 1. Authentication succeeds via 'domains=krb5'; Samba and IPA users exist but are |
| 442 | + ignored by that PAM line |
| 443 | + 2. Authentication succeeds via 'domains=ipa', since that line is tried first and now |
| 444 | + matches too |
| 445 | + :customerscenario: True |
| 446 | + """ |
| 447 | + client.local.user("user1").add(password="LocalSecret123") |
| 448 | + samba.user("user1").add(password="SambaSecret123") |
| 449 | + ipa.user("user1").add(password="IPASecret123") |
| 450 | + kdc.principal("user1").add(password="KDCSecret123") |
| 451 | + |
| 452 | + client.sssd.fs.write( |
| 453 | + "/etc/krb5.conf", |
| 454 | + textwrap.dedent(f""" |
| 455 | + [libdefaults] |
| 456 | + default_realm = {kdc.realm} |
| 457 | + dns_lookup_realm = false |
| 458 | + dns_lookup_kdc = false |
| 459 | + ticket_lifetime = 24h |
| 460 | + renew_lifetime = 7d |
| 461 | + forwardable = yes |
| 462 | +
|
| 463 | + [realms] |
| 464 | + {samba.realm} = {{ |
| 465 | + kdc = {samba.host.hostname} |
| 466 | + }} |
| 467 | + {ipa.realm} = {{ |
| 468 | + kdc = {ipa.host.hostname} |
| 469 | + }} |
| 470 | + {kdc.realm} = {{ |
| 471 | + kdc = {kdc.host.hostname}:88 |
| 472 | + admin_server = {kdc.host.hostname}:749 |
| 473 | + }} |
| 474 | + """).lstrip(), |
| 475 | + user="root", |
| 476 | + group="root", |
| 477 | + mode="0644", |
| 478 | + ) |
| 479 | + |
| 480 | + for name, role in (("samba", samba), ("ipa", ipa), ("krb5", kdc)): |
| 481 | + client.sssd.dom(name).update( |
| 482 | + enabled="true", |
| 483 | + id_provider="proxy", |
| 484 | + proxy_lib_name="files", |
| 485 | + auth_provider="krb5", |
| 486 | + krb5_realm=role.realm, |
| 487 | + krb5_server=role.host.hostname, |
| 488 | + ) |
| 489 | + client.sssd.sssd["domains"] = "samba, ipa, krb5" |
| 490 | + client.sssd.default_domain = "krb5" |
| 491 | + client.sssd.start() |
| 492 | + |
| 493 | + client.fs.backup("/etc/pam.d/su-l") |
| 494 | + client.fs.write( |
| 495 | + "/etc/pam.d/su-l", |
| 496 | + cleandoc(""" |
| 497 | + auth required pam_env.so |
| 498 | + auth sufficient pam_sss.so forward_pass domains=samba |
| 499 | + auth sufficient pam_sss.so forward_pass domains=ipa |
| 500 | + auth sufficient pam_sss.so forward_pass domains=krb5 |
| 501 | + auth required pam_deny.so |
| 502 | + account required pam_sss.so |
| 503 | + password required pam_sss.so |
| 504 | + session required pam_sss.so |
| 505 | + """), |
| 506 | + ) |
| 507 | + |
| 508 | + assert client.auth.su.password( |
| 509 | + "user1", "KDCSecret123" |
| 510 | + ), "Authentication should succeed via the matching 'domains=krb5' line!" |
| 511 | + |
| 512 | + # IPA always forces an immediate password-expiration on an administrative password reset, |
| 513 | + # even if 'password-expiration' is passed in the same call, so it must be pushed back out |
| 514 | + # in a separate modification. |
| 515 | + ipa.user("user1").modify(password="KDCSecret123") |
| 516 | + ipa.user("user1").modify(password_expiration="20380101120000Z") |
| 517 | + |
| 518 | + assert client.auth.su.password( |
| 519 | + "user1", "KDCSecret123" |
| 520 | + ), "Authentication should also succeed via the earlier 'domains=ipa' line once its password matches!" |
0 commit comments