Crash Course

This is a crash course for SSSD’s test framework. The course consists of multiple task that show the fundamental features and API. First, try to find the solution for the task by yourself using the information present in the documentation and inside the hints. Then display the task’s solution and compare it with yours.

Prepare the environment

See Running tests to se how to prepare the environment and run the tests.

Is everything working?

You should be ready to execute the tests, if you setup the environment correctly. Go to the system tests directory (src/tests/system) of SSSD repository and run the tests from this course with:

$ pytest --mh-config=./mhc.yaml --mh-log-path=./log -v ./docs/course/test_course.py

Take the Course

You can begin by creating a file inside the tests directory, for example tests/test_course.py and include the following imports:

from __future__ import annotations

import pytest

from sssd_test_framework.roles.client import Client
from sssd_test_framework.roles.generic import GenericADProvider, GenericProvider
from sssd_test_framework.roles.ipa import IPA
from sssd_test_framework.roles.ldap import LDAP
from sssd_test_framework.topology import KnownTopology, KnownTopologyGroup

Now try to run the file with pytest:

pytest --mh-config=./mhc.yaml --mh-log-path=./log -v ./tests/test_course.py

Does it work? Good. Now, you can continue with the following tasks.

  • Tasks 1 to 14 will teach you how to write some basic tests for LDAP.

  • Tasks 15 - 26 requires you to write the same tests but for IPA. You will see that it is pretty much the same except some differences in primary group - IPA creates primary groups automatically.

  • Tasks 26 - 31 are about topology parametrization - writing single test for multiple backends.

Task 1

Write your first test for the LDAP topology. The test does not have to do anything, just define it and make sure you can run it successfully.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.LDAP)
def test_ldap__skeleton(client: Client, ldap: LDAP):
    """
    :title: Pytest-mh test skeleton for the LDAP topology that does nothing
    :customerscenario: False
    """
    pass
Task 2
  1. Create a new test for LDAP topology.

  2. Add new LDAP user named tuser.

  3. Start SSSD on the client.

  4. Run id command on the client

  5. Check id result: check that the user exist and has correct name.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.LDAP)
def test_ldap__id__name(client: Client, ldap: LDAP):
    """
    :title: LDAP: Calling "id user" yields the expected user
    :setup:
        1. Add LDAP user "tuser"
        2. Start SSSD
    :steps:
        1. Run "id tuser"
    :expectedresults:
        1. "tuser" is returned
    :customerscenario: False
    """
    ldap.user("tuser").add()

    client.sssd.start()
    result = client.tools.id("tuser")
    assert result is not None
    assert result.user.name == "tuser"
Task 3
  1. Create a new test for LDAP topology.

  2. Add new LDAP user named tuser with uid and gid set to 10001.

  3. Start SSSD on the client.

  4. Run id command on the client

  5. Check id result: check that the user exist and has correct name, uid, gid.

  6. Also check that the primary group of the user does not exist.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.LDAP)
def test_ldap__id__name_and_id(client: Client, ldap: LDAP):
    """
    :title: LDAP: Calling "id user" yields the expected user, uid and gid
    :setup:
        1. Add LDAP user "tuser" with uid=10001, gid=10001
        2. Start SSSD
    :steps:
        1. Run "id tuser"
    :expectedresults:
        1. "tuser" is returned, uid is 10001, gid is 10001
    :customerscenario: False
    """
    ldap.user("tuser").add(uid=10001, gid=10001)

    client.sssd.start()
    result = client.tools.id("tuser")
    assert result is not None
    assert result.user.name == "tuser"
    assert result.user.id == 10001
    assert result.group.name is None
    assert result.group.id == 10001
Task 4
  1. Create a new test for LDAP topology.

  2. Add new LDAP user named tuser with uid and gid set to 10001.

  3. Add new LDAP group named tuser with gid set to 10001.

  4. Start SSSD on the client.

  5. Run id command on the client

  6. Check id result: check that the user exist and has correct name, uid, primary group name and gid.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.LDAP)
def test_ldap__id__primary_group(client: Client, ldap: LDAP):
    """
    :title: LDAP: Calling "id user" yields the expected user and expected primary group
    :setup:
        1. Add LDAP user "tuser" with uid=10001, gid=10001
        2. Add LDAP group "tuser" with gid 10001
        3. Start SSSD
    :steps:
        1. Run "id tuser"
    :expectedresults:
        1. "tuser" is returned, user and group name is "tuser", uid and gid is 10001
    :customerscenario: False
    """
    ldap.user("tuser").add(uid=10001, gid=10001)
    ldap.group("tuser").add(gid=10001)

    client.sssd.start()
    result = client.tools.id("tuser")
    assert result is not None
    assert result.user.name == "tuser"
    assert result.user.id == 10001
    assert result.group.name == "tuser"
    assert result.group.id == 10001
Task 5
  1. Create a new test for LDAP topology.

  2. Add new LDAP user named tuser with uid and gid set to 10001.

  3. Add new LDAP group named tuser with gid set to 10001.

  4. Add new LDAP group named users with gid set to 20001.

  5. Add user tuser as a member of group users

  6. Start SSSD on the client.

  7. Run id command on the client

  8. Check id result: check that the user exist and has correct name, uid, primary group name and gid.

  9. Check that the user is member of users

Display hints
Display solution
@pytest.mark.topology(KnownTopology.LDAP)
def test_ldap__id__one_supplementary_group(client: Client, ldap: LDAP):
    """
    :title: LDAP: Calling "id user" yields the expected user and one expected supplementary groups
    :setup:
        1. Add LDAP user "tuser" with uid=10001, gid=10001
        2. Add LDAP group "tuser" with gid 10001
        3. Add LDAP group "users" with gid 20001
        4. Make user "tuser" member of "users"
        5. Start SSSD
    :steps:
        1. Run "id tuser"
    :expectedresults:
        1. "tuser" is returned and the user is member of "users"
    :customerscenario: False
    """
    u = ldap.user("tuser").add(uid=10001, gid=10001)
    ldap.group("tuser").add(gid=10001)
    ldap.group("users").add(gid=20001).add_member(u)

    client.sssd.start()
    result = client.tools.id("tuser")
    assert result is not None
    assert result.user.name == "tuser"
    assert result.user.id == 10001
    assert result.group.name == "tuser"
    assert result.group.id == 10001
    assert result.memberof("users")

See also

The memberof method allows you to use multiple input types. Including group name (string), group id (int) and list of names or ids.

Task 6
  1. Create a new test for LDAP topology.

  2. Add new LDAP user named tuser with uid and gid set to 10001.

  3. Add new LDAP group named tuser with gid set to 10001.

  4. Add two LDAP groups named users and admins without any gid set.

  5. Add user tuser as a member of groups users and admins

  6. Start SSSD on the client.

  7. Run id command on the client

  8. Check id result: check that the user exist and has correct name, uid, primary group name and gid.

  9. Check that the user is member of both users and admins

Display hints
Display solution
@pytest.mark.topology(KnownTopology.LDAP)
def test_ldap__id__two_supplementary_groups(client: Client, ldap: LDAP):
    """
    :title: LDAP: Calling "id user" yields the expected user and two expected supplementary groups
    :setup:
        1. Add LDAP user "tuser" with uid=10001, gid=10001
        2. Add LDAP group "tuser" with gid 10001
        3. Add LDAP group "users"
        4. Add LDAP group "admins"
        5. Make user "tuser" member of "users" and "admins"
        6. Start SSSD
    :steps:
        1. Run "id tuser"
    :expectedresults:
        1. "tuser" is returned and the user is member of "users" and "admins"
    :customerscenario: False
    """
    u = ldap.user("tuser").add(uid=10001, gid=10001)
    ldap.group("tuser").add(gid=10001)
    ldap.group("users").add().add_member(u)
    ldap.group("admins").add().add_member(u)

    client.sssd.start()
    result = client.tools.id("tuser")
    assert result is not None
    assert result.user.name == "tuser"
    assert result.user.id == 10001
    assert result.group.name == "tuser"
    assert result.group.id == 10001
    assert result.memberof(["users", "admins"])

Note

If you omit uid or gid attribute on user or group then the id is automatically generated by the framework. This is useful for cases where the id is not important.

Task 7
  1. Create a new test for LDAP topology.

  2. Add new LDAP user named tuser with password set to Secret123.

  3. Start SSSD on the client.

  4. Test that the user can authenticate via su with the password.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.LDAP)
def test_ldap__su(client: Client, ldap: LDAP):
    """
    :title: LDAP: Authenticate user with password using "su"
    :setup:
        1. Add LDAP user "tuser" with password "Secret123"
        2. Start SSSD
    :steps:
        1. Run "su tuser" with correct password
    :expectedresults:
        1. Authentication is successful
    :customerscenario: False
    """
    ldap.user("tuser").add(password="Secret123")

    client.sssd.start()
    assert client.auth.su.password("tuser", "Secret123")

Note

The password parameter defaults to Secret123 so it can be omitted. However, it is a good practice to set it explicitly when you test authentication to help understand the test case.

Task 8
  1. Create a new test for LDAP topology.

  2. Add new LDAP user named tuser with password set to Secret123.

  3. Start SSSD on the client.

  4. Test that the user can authenticate via ssh with the password.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.LDAP)
def test_ldap__ssh(client: Client, ldap: LDAP):
    """
    :title: LDAP: Authenticate user with password using "ssh"
    :setup:
        1. Add LDAP user "tuser" with password "Secret123"
        2. Start SSSD
    :steps:
        1. Run "ssh tuser@localhost" with correct password
    :expectedresults:
        1. Authentication is successful
    :customerscenario: False
    """
    ldap.user("tuser").add(password="Secret123")

    client.sssd.start()
    assert client.auth.ssh.password("tuser", "Secret123")
Task 9
  1. Create a new test for LDAP topology.

  2. Parametrize a test case argument with two values: su and ssh

  3. Add new LDAP user named tuser with password set to Secret123.

  4. Start SSSD on the client.

  5. Test that the user can authenticate via su and ssh with the password, use the parametrized value to determine which method should be used.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.LDAP)
@pytest.mark.parametrize("method", ["su", "ssh"])
def test_ldap__password_authentication(client: Client, ldap: LDAP, method: str):
    """
    :title: LDAP: Authenticate user with password using "@method"
    :setup:
        1. Add LDAP user "tuser" with password "Secret123"
        2. Start SSSD
    :steps:
        1. Try authenticate the user with password using @method
    :expectedresults:
        1. Authentication is successful
    :customerscenario: False
    """
    ldap.user("tuser").add(password="Secret123")

    client.sssd.start()
    assert client.auth.parametrize(method).password("tuser", "Secret123")

Note

This produces two test runs: one for su authentication and one for ssh. It is better to parametrize the test instead of calling both su and ssh in one test run so you can test only one thing at a time if you ever need to debug failure.

Task 10
  1. Create a new test for LDAP topology.

  2. Add new LDAP user named tuser with password set to Secret123.

  3. Add new sudo rule to LDAP that allows the user to run /bin/ls on ALL hosts.

  4. Select sssd authselect profile with with-sudo enabled.

  5. Enable sudo responder in SSSD.

  6. Start SSSD on the client.

  7. Check that tuser can run only /bin/ls command and only as root.

  8. Check that running /bin/ls through sudo actually works for tuser.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.LDAP)
def test_ldap__sudo__passwd(client: Client, ldap: LDAP):
    """
    :title: LDAP: User can run command via sudo when authentication is required
    :setup:
        1. Add LDAP user "tuser" with password "Secret123"
        2. Create sudo rule that allows the user to run "/bin/ls" as root on all hosts
        3. Enable SSSD sudo responder and configure sudo to use SSSD
        4. Start SSSD
    :steps:
        1. Login as "tuser" and run "sudo -l" with user password
        2. Login as "tuser" and run "sudo /bin/ls /root" with user password
    :expectedresults:
        1. The created rule is listed in the output
        2. The command run successfully as root
    :customerscenario: False
    """
    u = ldap.user("tuser").add(password="Secret123")
    ldap.sudorule("allow_ls").add(user=u, host="ALL", command="/bin/ls")

    client.sssd.common.sudo()
    client.sssd.start()

    assert client.auth.sudo.list("tuser", "Secret123", expected=["(root) /bin/ls"])
    assert client.auth.sudo.run("tuser", "Secret123", command="/bin/ls /root")

Note

You need to enable with-sudo using authselect so sudo can read rules from SSSD. You can use sssd_test_framework.utils.sssd.SSSDCommonConfiguration.sudo() as a shortcut for selecting authselect profile and enabling the sudo responder.

Task 11
  1. Create a new test for LDAP topology.

  2. Add new LDAP user named tuser.

  3. Add new sudo rule to LDAP that allows the user to run /bin/ls on ALL hosts but without requiring authentication (nopasswd).

  4. Select sssd authselect profile with with-sudo enabled.

  5. Enable sudo responder in SSSD.

  6. Start SSSD on the client.

  7. Check that tuser can run only /bin/ls command without a password and only as root.

  8. Check that running /bin/ls through sudo actually works for tuser without a password.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.LDAP)
def test_ldap__sudo__nopasswd(client: Client, ldap: LDAP):
    """
    :title: LDAP: User can run command via sudo when authentication is not required
    :setup:
        1. Add LDAP user "tuser"
        2. Create sudo rule that allows the user to run "/bin/ls" as root on all hosts, !authenticate option is set
        3. Enable SSSD sudo responder and configure sudo to use SSSD
        4. Start SSSD
    :steps:
        1. Login as "tuser" and run "sudo -l", no password is provided
        2. Login as "tuser" and run "sudo /bin/ls /root", no password is provided
    :expectedresults:
        1. The created rule is listed in the output
        2. The command run successfully as root
    :customerscenario: False
    """
    u = ldap.user("tuser").add()
    ldap.sudorule("allow_ls").add(user=u, host="ALL", command="/bin/ls", nopasswd=True)

    client.sssd.common.sudo()
    client.sssd.start()

    assert client.auth.sudo.list("tuser", expected=["(root) NOPASSWD: /bin/ls"])
    assert client.auth.sudo.run("tuser", command="/bin/ls /root")
Task 12
  1. Create a new test for LDAP topology.

  2. Add new LDAP user named tuser.

  3. Set use_fully_qualified_names to true on the client.

  4. Start SSSD on the client.

  5. Check that tuser does not exist.

  6. Check that tuser@test exists.

Display hints
Display solution

@pytest.mark.topology(KnownTopology.LDAP)
def test_ldap__id__required_fqn(client: Client, ldap: LDAP):
    """
    :title: LDAP: Calling "id user@domain" yields the expected user
    :setup:
        1. Add LDAP user "tuser"
        2. Set use_fully_qualified_names to true for the LDAP domain
        3. Start SSSD
    :steps:
        1. Run "id tuser@domain"
    :expectedresults:
        1. "tuser" is returned
    :customerscenario: False
    """
    ldap.user("tuser").add()

    client.sssd.domain["use_fully_qualified_names"] = "true"
    client.sssd.start()

    assert client.tools.id("tuser") is None
    assert client.tools.id("tuser@test") is not None

Note

Changes to the configuration are automatically applied when calling client.sssd.start(). You can override this behavior by calling client.sssd.start(apply_config=False).

Task 13
  1. Create a new test for LDAP topology.

  2. Add new LDAP user named tuser.

  3. Set use_fully_qualified_name to true on the client (intentionally create a typo in the option name).

  4. Start SSSD on the client.

  5. Assert that an Exception was risen

Display hints
Display solution
@pytest.mark.topology(KnownTopology.LDAP)
def test_ldap__config_typo(client: Client, ldap: LDAP):
    """
    :title: LDAP: Typo in SSSD option makes sssctl config-check fail
    :setup:
        1. Add LDAP user "tuser"
        2. Set use_fully_qualified_name (not _names) to true for the LDAP domain
    :steps:
        1. Run sssctl config-check
    :expectedresults:
        1. The command fails
    :customerscenario: False

    Note that client.sssd.start() calls sssctl config-check prior starting SSSD.
    """
    ldap.user("tuser").add()

    with pytest.raises(Exception):
        client.sssd.domain["use_fully_qualified_name"] = "true"
        client.sssd.start()

Note

Starting SSSD with client.sssd.start() automatically validates configuration with sssctl config-check. If the validation fails, it raises an exception. You can override this behavior by calling client.sssd.start(check_config=False).

Task 14
  1. Create a new test for LDAP topology.

  2. Add new LDAP user named tuser with uid and gid set to 10001.

  3. Add new LDAP group named tuser with gid set to 10001, use rfc2307bis schema.

  4. Add two LDAP groups named users and admins without any gid set, use rfc2307bis schema.

  5. Add user tuser as a member of groups users and admins

  6. Set ldap_schema to rfc2307bis on the client

  7. Start SSSD on the client.

  8. Run id command on the client

  9. Check id result: check that the user exist and has correct name, uid, primary group name and gid.

  10. Check that the user is member of both users and admins

Display hints
Display solution
@pytest.mark.topology(KnownTopology.LDAP)
def test_ldap__id__rfc2307bis(client: Client, ldap: LDAP):
    """
    :title: LDAP: Calling "id user" yields the expected user and groups with rfc2307bis schema
    :setup:
        1. Add LDAP user "tuser" with uid=10001, gid=10001
        2. Add LDAP group "tuser" with gid 10001 using rfc2307bis schema
        3. Add LDAP group "users" using rfc2307bis schema
        4. Add LDAP group "admins" using rfc2307bis schema
        5. Make user "tuser" member of "users" and "admins"
        6. Set ldap_schema = rfc2307bis for the LDAP domain
        7. Start SSSD
    :steps:
        1. Run "id tuser"
    :expectedresults:
        1. "tuser" is returned and the user is member of "users" and "admins"
    :customerscenario: False
    """
    u = ldap.user("tuser").add(uid=10001, gid=10001)
    ldap.group("tuser", rfc2307bis=True).add(gid=10001)
    ldap.group("users", rfc2307bis=True).add().add_member(u)
    ldap.group("admins", rfc2307bis=True).add().add_member(u)

    client.sssd.domain["ldap_schema"] = "rfc2307bis"
    client.sssd.start()

    result = client.tools.id("tuser")
    assert result is not None
    assert result.user.name == "tuser"
    assert result.user.id == 10001
    assert result.group.name == "tuser"
    assert result.group.id == 10001
    assert result.memberof(["users", "admins"])
Task 15

Write your first test for the IPA topology. The test does not have to do anything, just define it and make sure you can run it successfully.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.IPA)
def test_ipa__skeleton(client: Client, ipa: IPA):
    """
    :title: Pytest-mh test skeleton for the IPA topology that does nothing
    :customerscenario: False
    """
    pass
Task 16
  1. Create a new test for IPA topology.

  2. Add new IPA user named tuser.

  3. Start SSSD on the client.

  4. Run id command on the client

  5. Check id result: check that the user exist and has correct name.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.IPA)
def test_ipa__id__name(client: Client, ipa: IPA):
    """
    :title: IPA: Calling "id user" yields the expected user
    :setup:
        1. Add IPA user "tuser"
        2. Start SSSD
    :steps:
        1. Run "id tuser"
    :expectedresults:
        1. "tuser" is returned
    :customerscenario: False
    """
    ipa.user("tuser").add()

    client.sssd.start()
    result = client.tools.id("tuser")
    assert result is not None
    assert result.user.name == "tuser"
Task 17
  1. Create a new test for IPA topology.

  2. Add new IPA user named tuser with uid and gid set to 10001.

  3. Start SSSD on the client.

  4. Run id command on the client

  5. Check id result: check that the user exist and has correct name, uid, primary group name and gid.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.IPA)
def test_ipa__id__primary_group(client: Client, ipa: IPA):
    """
    :title: IPA: Calling "id user" yields the expected user and primary group
    :setup:
        1. Add IPA user "tuser" with uid=10001, gid=10001
        2. Start SSSD
    :steps:
        1. Run "id tuser"
    :expectedresults:
        1. "tuser" is returned, uid is 10001, gid is 10001
    :customerscenario: False
    """
    ipa.user("tuser").add(uid=10001, gid=10001)

    # Primary group is created automatically, we need to skip this step
    # ipa.group('tuser').add(gid=10001)

    client.sssd.start()
    result = client.tools.id("tuser")
    assert result is not None
    assert result.user.name == "tuser"
    assert result.user.id == 10001
    assert result.group.name == "tuser"
    assert result.group.id == 10001

Note

Unlike LDAP, IPA creates the primary group automatically therefore we do not have to add it ourselves.

Task 18
  1. Create a new test for IPA topology.

  2. Add new IPA user named tuser with uid and gid set to 10001.

  3. Add new IPA group named users with gid set to 20001.

  4. Add user tuser as a member of group users

  5. Start SSSD on the client.

  6. Run id command on the client

  7. Check id result: check that the user exist and has correct name, uid, primary group name and gid.

  8. Check that the user is member of users

Display hints
Display solution
@pytest.mark.topology(KnownTopology.IPA)
def test_ipa__id__one_supplementary_group(client: Client, ipa: IPA):
    """
    :title: IPA: Calling "id user" yields the expected user and one expected supplementary groups
    :setup:
        1. Add IPA user "tuser" with uid=10001, gid=10001
        2. Add IPA group "users" with gid 20001
        3. Make user "tuser" member of "users"
        4. Start SSSD
    :steps:
        1. Run "id tuser"
    :expectedresults:
        1. "tuser" is returned and the user is member of "users"
    :customerscenario: False
    """
    u = ipa.user("tuser").add(uid=10001, gid=10001)
    # Primary group is created automatically, we need to skip this step
    # ipa.group('tuser').add(gid=10001)
    ipa.group("users").add(gid=20001).add_member(u)

    client.sssd.start()
    result = client.tools.id("tuser")
    assert result is not None
    assert result.user.name == "tuser"
    assert result.user.id == 10001
    assert result.group.name == "tuser"
    assert result.group.id == 10001
    assert result.memberof("users")
Task 19
  1. Create a new test for IPA topology.

  2. Add new IPA user named tuser with uid and gid set to 10001.

  3. Add new IPA group named users without any gid set.

  4. Create a group object for IPA group admins that already exist (it is created by IPA installation)

  5. Add user tuser as a member of groups users and admins

  6. Start SSSD on the client.

  7. Run id command on the client

  8. Check id result: check that the user exist and has correct name, uid, primary group name and gid.

  9. Check that the user is member of both users and admins

Display hints
Display solution
@pytest.mark.topology(KnownTopology.IPA)
def test_ipa__id__two_supplementary_groups(client: Client, ipa: IPA):
    """
    :title: IPA: Calling "id user" yields the expected user and two expected supplementary groups
    :setup:
        1. Add IPA user "tuser" with uid=10001, gid=10001
        2. Add IPA group "users"
        3. Make user "tuser" member of "users" and "admins"
        4. Start SSSD
    :steps:
        1. Run "id tuser"
    :expectedresults:
        1. "tuser" is returned and the user is member of "users" and "admins"
    :customerscenario: False
    """
    u = ipa.user("tuser").add(uid=10001, gid=10001)
    # Primary group is created automatically, we need to skip this step
    # ipa.group('tuser').add(gid=10001)
    ipa.group("users").add().add_member(u)
    # Group admins is already present in IPA so we just omit add() and use add_member() only
    # ipa.group('admins').add().add_member(u)
    ipa.group("admins").add_member(u)

    client.sssd.start()
    result = client.tools.id("tuser")
    assert result is not None
    assert result.user.name == "tuser"
    assert result.user.id == 10001
    assert result.group.name == "tuser"
    assert result.group.id == 10001
    assert result.memberof(["users", "admins"])
Task 20
  1. Create a new test for IPA topology.

  2. Add new IPA user named tuser with password set to Secret123.

  3. Start SSSD on the client.

  4. Test that the user can authenticate via su with the password.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.IPA)
def test_ipa__su(client: Client, ipa: IPA):
    """
    :title: IPA: Authenticate user with password using "su"
    :setup:
        1. Add IPA user "tuser" with password "Secret123"
        2. Start SSSD
    :steps:
        1. Run "su tuser" with correct password
    :expectedresults:
        1. Authentication is successful
    :customerscenario: False
    """
    ipa.user("tuser").add(password="Secret123")

    client.sssd.start()
    assert client.auth.su.password("tuser", "Secret123")
Task 21
  1. Create a new test for IPA topology.

  2. Add new IPA user named tuser with password set to Secret123.

  3. Start SSSD on the client.

  4. Test that the user can authenticate via ssh with the password.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.IPA)
def test_ipa__ssh(client: Client, ipa: IPA):
    """
    :title: IPA: Authenticate user with password using "ssh"
    :setup:
        1. Add IPA user "tuser" with password "Secret123"
        2. Start SSSD
    :steps:
        1. Run "ssh tuser@localhost" with correct password
    :expectedresults:
        1. Authentication is successful
    :customerscenario: False
    """
    ipa.user("tuser").add(password="Secret123")

    client.sssd.start()
    assert client.auth.ssh.password("tuser", "Secret123")
Task 22
  1. Create a new test for IPA topology.

  2. Parametrize a test case argument with two values: su and ssh

  3. Add new IPA user named tuser with password set to Secret123.

  4. Start SSSD on the client.

  5. Test that the user can authenticate via su and ssh with the password, use the parametrized value to determine which method should be used.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.IPA)
@pytest.mark.parametrize("method", ["su", "ssh"])
def test_ipa__password_authentication(client: Client, ipa: IPA, method: str):
    """
    :title: IPA: Authenticate user with password using "@method"
    :setup:
        1. Add IPA user "tuser" with password "Secret123"
        2. Start SSSD
    :steps:
        1. Try authenticate the user with password using @method
    :expectedresults:
        1. Authentication is successful
    :customerscenario: False
    """
    ipa.user("tuser").add(password="Secret123")

    client.sssd.start()
    assert client.auth.parametrize(method).password("tuser", "Secret123")
Task 23
  1. Create a new test for IPA topology.

  2. Add new IPA user named tuser with password set to Secret123.

  3. Add new sudo rule to IPA that allows the user to run /bin/ls on ALL hosts.

  4. Select sssd authselect profile with with-sudo enabled.

  5. Enable sudo responder in SSSD.

  6. Start SSSD on the client.

  7. Check that tuser can run only /bin/ls command and only as root.

  8. Check that running /bin/ls through sudo actually works for tuser.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.IPA)
def test_ipa__sudo__passwd(client: Client, ipa: IPA):
    """
    :title: IPA: User can run command via sudo when authentication is required
    :setup:
        1. Add IPA user "tuser" with password "Secret123"
        2. Create sudo rule that allows the user to run "/bin/ls" as root on all hosts
        3. Enable SSSD sudo responder and configure sudo to use SSSD
        4. Start SSSD
    :steps:
        1. Login as "tuser" and run "sudo -l" with user password
        2. Login as "tuser" and run "sudo /bin/ls /root" with user password
    :expectedresults:
        1. The created rule is listed in the output
        2. The command run successfully as root
    :customerscenario: False
    """
    u = ipa.user("tuser").add(password="Secret123")
    ipa.sudorule("allow_ls").add(user=u, host="ALL", command="/bin/ls")

    client.sssd.common.sudo()
    client.sssd.start()

    assert client.auth.sudo.list("tuser", "Secret123", expected=["(root) /bin/ls"])
    assert client.auth.sudo.run("tuser", "Secret123", command="/bin/ls /root")
Task 24
  1. Create a new test for IPA topology.

  2. Add new IPA user named tuser.

  3. Add new sudo rule to IPA that allows the user to run /bin/ls on ALL hosts but without requiring authentication (nopasswd).

  4. Select sssd authselect profile with with-sudo enabled.

  5. Enable sudo responder in SSSD.

  6. Start SSSD on the client.

  7. Check that tuser can run only /bin/ls command without a password and only as root.

  8. Check that running /bin/ls through sudo actually works for tuser without a password.

Display hints
Display solution

@pytest.mark.topology(KnownTopology.IPA)
def test_ipa__sudo__nopasswd(client: Client, ipa: IPA):
    """
    :title: IPA: User can run command via sudo when authentication is not required
    :setup:
        1. Add IPA user "tuser"
        2. Create sudo rule that allows the user to run "/bin/ls" as root on all hosts, !authenticate option is set
        3. Enable SSSD sudo responder and configure sudo to use SSSD
        4. Start SSSD
    :steps:
        1. Login as "tuser" and run "sudo -l", no password is provided
        2. Login as "tuser" and run "sudo /bin/ls /root", no password is provided
    :expectedresults:
        1. The created rule is listed in the output
        2. The command run successfully as root
    :customerscenario: False
    """
    u = ipa.user("tuser").add()
    ipa.sudorule("allow_ls").add(user=u, host="ALL", command="/bin/ls", nopasswd=True)

    client.sssd.common.sudo()
    client.sssd.start()

    assert client.auth.sudo.list("tuser", expected=["(root) NOPASSWD: /bin/ls"])
    assert client.auth.sudo.run("tuser", command="/bin/ls /root")
Task 25
  1. Create a new test for IPA topology.

  2. Add new IPA user named tuser.

  3. Set use_fully_qualified_names to true on the client.

  4. Start SSSD on the client.

  5. Check that tuser does not exist.

  6. Check that tuser@test exists.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.IPA)
def test_ipa__id__required_fqn(client: Client, ipa: IPA):
    """
    :title: IPA: Calling "id user@domain" yields the expected user
    :setup:
        1. Add IPA user "tuser"
        2. Set use_fully_qualified_names to true for the IPA domain
        3. Start SSSD
    :steps:
        1. Run "id tuser@domain"
    :expectedresults:
        1. "tuser" is returned
    :customerscenario: False
    """
    ipa.user("tuser").add()

    client.sssd.domain["use_fully_qualified_names"] = "true"
    client.sssd.start()

    assert client.tools.id("tuser") is None
    assert client.tools.id("tuser@test") is not None
Task 26
  1. Create a new test for IPA topology.

  2. Add new IPA user named tuser.

  3. Set use_fully_qualified_name to true on the client (intentionally create a typo in the option name).

  4. Start SSSD on the client.

  5. Assert that an Exception was risen

Display hints
Display solution
@pytest.mark.topology(KnownTopology.IPA)
def test_ipa__config_typo(client: Client, ipa: IPA):
    """
    :title: IPA: Typo in SSSD option makes sssctl config-check fail
    :setup:
        1. Add IPA user "tuser"
        2. Set use_fully_qualified_name (not _names) to true for the IPA domain
    :steps:
        1. Run sssctl config-check
    :expectedresults:
        1. The command fails
    :customerscenario: False

    Note that client.sssd.start() calls sssctl config-check prior starting SSSD.
    """
    ipa.user("tuser").add()

    with pytest.raises(Exception):
        client.sssd.domain["use_fully_qualified_name"] = "true"
        client.sssd.start()
Task 27
  1. Create a new parametrized test for LDAP, IPA, Samba and AD topology.

  2. Add new user named tuser.

  3. Add new groups tgroup_1 and tgroup_2

  4. Add the user tuser as a member of tgroup_1 and tgroup_2

  5. Start SSSD on the client.

  6. Run id command on the client

  7. Check id result: check that the user exist and has correct name.

  8. Check that the user is member of tgroup_1 and tgroup_2

Display hints
Display solution
@pytest.mark.topology(KnownTopologyGroup.AnyProvider)
def test_id__supplementary_groups(client: Client, provider: GenericProvider):
    """
    :title: Calling "id user" yields the expected user and supplementary groups
    :setup:
        1. Add user "tuser"
        2. Add group "tgroup_1"
        3. Add group "tgroup_2"
        4. Make user "tuser" member of "tgroup_1" and "tgroup_2"
        5. Start SSSD
    :steps:
        1. Run "id tuser"
    :expectedresults:
        1. "tuser" is returned and the user is member of "tgroup_1" and "tgroup_2"
    :customerscenario: False
    """
    u = provider.user("tuser").add()
    provider.group("tgroup_1").add().add_member(u)
    provider.group("tgroup_2").add().add_member(u)

    client.sssd.start()
    result = client.tools.id("tuser")

    assert result is not None
    assert result.user.name == "tuser"
    assert result.memberof(["tgroup_1", "tgroup_2"])

Note

We can write single test that can be run on multiple topologies. This is achieved by using well-defined API that is implemented by all providers. However, there are some distinctions that you need to be aware of - for example LDAP does not create primary group automatically, IPA creates it automatically and Samba and AD uses Domain Users as the primary group.

Task 28
  1. Create a new parametrized test for Samba and AD topology.

  2. Add new user named tuser.

  3. Start SSSD on the client.

  4. Run id command on the client

  5. Check id result: check that the user exist and has correct name.

  6. Check that the user is member of domain users (Active Directory built-in group)

Display hints
Display solution
@pytest.mark.topology(KnownTopologyGroup.AnyAD)
def test_ad__id__domain_users(client: Client, provider: GenericADProvider):
    """
    :title: AD: The primary user group is "Domain Users"
    :setup:
        1. Add user "tuser"
        2. Start SSSD
    :steps:
        1. Run "id tuser"
    :expectedresults:
        1. "tuser" is returned and the primary group is "Domain Users" (case insensitive)
    :customerscenario: False
    """
    provider.user("tuser").add()

    client.sssd.start()

    result = client.tools.id("tuser")
    assert result is not None
    assert result.user.name == "tuser"
    assert result.group.name is not None
    assert result.group.name.lower() == "domain users"
Task 29
  1. Create a new parametrized test for LDAP and IPA topology.

  2. Add new user named tuser with uid and gid set to 10001.

  3. Create user’s primary group object only if the topology is LDAP

  4. Start SSSD on the client.

  5. Run id command on the client

  6. Check id result: check that the user exist and has correct name, uid, primary group name and gid.

Display hints
Display solution
@pytest.mark.topology(KnownTopology.LDAP)
@pytest.mark.topology(KnownTopology.IPA)
def test_id__primary_group(client: Client, provider: GenericProvider):
    """
    :title: Calling "id user" yields the expected user and expected primary group
    :setup:
        1. Add user "tuser" with uid=10001, gid=10001
        2. Add group "tuser" with gid 10001
        3. Start SSSD
    :steps:
        1. Run "id tuser"
    :expectedresults:
        1. "tuser" is returned, user and group name is "tuser", uid and gid is 10001
    :customerscenario: False
    """
    provider.user("tuser").add(uid=10001, gid=10001)

    if isinstance(provider, LDAP):
        provider.group("tuser").add(gid=10001)

    client.sssd.start()
    result = client.tools.id("tuser")
    assert result is not None
    assert result.user.name == "tuser"
    assert result.user.id == 10001
    assert result.group.name == "tuser"
    assert result.group.id == 10001
Task 30
  1. Create a new test for LDAP, IPA, Samba and AD topology.

  2. Add new user named tuser.

  3. Add new sudo rule defaults and set !authenticate option

  4. Add new sudo rule to that ALL users on ALL hosts run ALL commands.

  5. Select sssd authselect profile with with-sudo enabled.

  6. Enable sudo responder in SSSD.

  7. Start SSSD on the client.

  8. Check that tuser can run ALL commands without a password but only as root.

  9. Check that running /bin/ls through sudo actually works for tuser without a password.

Display hints
Display solution
@pytest.mark.topology(KnownTopologyGroup.AnyProvider)
def test_sudo__defaults_nopasswd(client: Client, provider: GenericProvider):
    """
    :title: User can run command via sudo when authentication is not required in defaults
    :setup:
        1. Add user "tuser"
        2. Create sudo rule "defaults" with sudoOption set to !authenticate
        3. Create sudo rule that allows the all users to run all commands as root on all hosts
        4. Enable SSSD sudo responder and configure sudo to use SSSD
        5. Start SSSD
    :steps:
        1. Login as "tuser" and run "sudo -l", no password is provided
        2. Login as "tuser" and run "sudo /bin/ls /root", no password is provided
    :expectedresults:
        1. The created rule is listed in the output
        2. The command run successfully as root
    :customerscenario: False
    """
    provider.user("tuser").add()
    provider.sudorule("defaults").add(nopasswd=True)
    provider.sudorule("allow_all").add(user="ALL", host="ALL", command="ALL")

    client.sssd.common.sudo()
    client.sssd.start()

    assert client.auth.sudo.list("tuser", expected=["(root) ALL"])
    assert client.auth.sudo.run("tuser", command="/bin/ls /root")
Task 31
  1. Create a new parametrized test for LDAP, IPA, Samba and AD topology.

  2. Parametrize a test case argument with two values: su and ssh

  3. Add new user named tuser with password set to Secret123.

  4. Start SSSD on the client.

  5. Test that the user can authenticate via su and ssh with the password, use the parametrized value to determine which method should be used.

Display hints
Display solution
@pytest.mark.topology(KnownTopologyGroup.AnyProvider)
@pytest.mark.parametrize("method", ["su", "ssh"])
def test_authentication__password(client: Client, provider: GenericProvider, method: str):
    """
    :title: Authenticate user with password using "@method"
    :setup:
        1. Add user "tuser" with password "Secret123"
        2. Start SSSD
    :steps:
        1. Try authenticate the user with password using @method
    :expectedresults:
        1. Authentication is successful
    :customerscenario: False
    """
    provider.user("tuser").add(password="Secret123")

    client.sssd.start()
    assert client.auth.parametrize(method).password("tuser", "Secret123")