From 7df777f54b37803bedfd8957a1c131ec269f8179 Mon Sep 17 00:00:00 2001 From: Dan Lavu Date: Wed, 13 Sep 2023 13:29:25 -0400 Subject: [PATCH] tests: consolidation, refactoring and organizing, renaming of some tests - added markers to pytest.ini - added markers to tests - consolidated two sssctl test files into one, sssctl_config_check.py and sssctl.py - renamed test_id.py, to test_identity.py, just to match the marker groups - renamed the test cases in test_identity.py to be more readable - renamed test_ldap_extra_attrs.py to test_schema.py , after looking at the tests, its testing the schema attributes - appended test_shadow.py to test_ldap.py , tests shadowlastchange = 0 in LDAP --- .../basic/test_sssctl_config_check.py | 6 +- src/tests/system/pytest.ini | 2 +- .../tests/{test_id.py => test_identity.py} | 26 ++-- src/tests/system/tests/test_kcm.py | 2 +- src/tests/system/tests/test_ldap.py | 39 ++++++ ...est_ldap_extra_attrs.py => test_schema.py} | 4 +- src/tests/system/tests/test_shadow.py | 50 ------- src/tests/system/tests/test_sssctl.py | 92 ++++++++++++- .../system/tests/test_sssctl_config_check.py | 123 ------------------ 9 files changed, 150 insertions(+), 194 deletions(-) rename src/tests/system/tests/{test_id.py => test_identity.py} (93%) rename src/tests/system/tests/{test_ldap_extra_attrs.py => test_schema.py} (91%) delete mode 100644 src/tests/system/tests/test_shadow.py delete mode 100644 src/tests/system/tests/test_sssctl_config_check.py diff --git a/src/tests/multihost/basic/test_sssctl_config_check.py b/src/tests/multihost/basic/test_sssctl_config_check.py index f70967e6056..1de2e958d9a 100644 --- a/src/tests/multihost/basic/test_sssctl_config_check.py +++ b/src/tests/multihost/basic/test_sssctl_config_check.py @@ -13,7 +13,7 @@ class TestSssctlConfigCheck(object): - @pytest.mark.converted('test_sssctl_config_check.py', 'test_sssctl_config_check__typo_option_name') + @pytest.mark.converted('test_sssctl.py', 'test_sssctl__typo_option_name') def test_verify_typo_option_name(self, multihost): """ :title: sssctl: Verify typos in option name (not value) @@ -44,7 +44,7 @@ def test_verify_typo_option_name(self, multihost): multihost.master[0].run_command(['/bin/cp', '-a', cfgput, cfgget], raiseonerr=False) - @pytest.mark.converted('test_sssctl_config_check.py', 'test_sssctl_config_check__typo_domain_name') + @pytest.mark.converted('test_sssctl.py', 'test_sssctl__typo_domain_name') def test_verify_typo_domain_name(self, multihost): """ :title: sssctl: Verify typos in domain name of configuration file @@ -74,7 +74,7 @@ def test_verify_typo_domain_name(self, multihost): multihost.master[0].run_command(['/bin/cp', '-a', cfgput, cfgget], raiseonerr=False) - @pytest.mark.converted('test_sssctl_config_check.py', 'test_sssctl_config_check__misplaced_option') + @pytest.mark.converted('test_sssctl.py', 'test_sssctl__misplaced_option') def test_misplaced_option(self, multihost): """ :title: sssctl: Verify misplace options in default configuration file diff --git a/src/tests/system/pytest.ini b/src/tests/system/pytest.ini index ecc40bc8518..963dd23634a 100644 --- a/src/tests/system/pytest.ini +++ b/src/tests/system/pytest.ini @@ -1,3 +1,4 @@ +# For marker descriptions please look at https://tests.sssd.io/en/latest/marks.html [pytest] addopts = --strict-markers testpaths = tests @@ -12,4 +13,3 @@ markers = tools: ticket_tools = bz,gh,jira -# For marker descriptions please look at https://tests.sssd.io/en/latest/marks.html diff --git a/src/tests/system/tests/test_id.py b/src/tests/system/tests/test_identity.py similarity index 93% rename from src/tests/system/tests/test_id.py rename to src/tests/system/tests/test_identity.py index 8ee34b6f729..f09d5bb61fd 100644 --- a/src/tests/system/tests/test_id.py +++ b/src/tests/system/tests/test_identity.py @@ -1,5 +1,5 @@ """ -SSSD Client identification +SSSD Client identity Lookups :requirement: IDM-SSSD-REQ: Client side performance improvements """ @@ -14,7 +14,7 @@ @pytest.mark.importance("critical") @pytest.mark.topology(KnownTopologyGroup.AnyProvider) -def test_id__getpwnam(client: Client, provider: GenericProvider): +def test_identity__lookup_username_with_id(client: Client, provider: GenericProvider): """ :title: Resolve user by name with id :setup: @@ -47,7 +47,7 @@ def test_id__getpwnam(client: Client, provider: GenericProvider): @pytest.mark.importance("critical") @pytest.mark.topology(KnownTopologyGroup.AnyProvider) -def test_id__getpwuid(client: Client, provider: GenericProvider): +def test_identity__lookup_uid_with_id(client: Client, provider: GenericProvider): """ :title: Resolve user by uid with id :setup: @@ -80,7 +80,7 @@ def test_id__getpwuid(client: Client, provider: GenericProvider): @pytest.mark.importance("critical") @pytest.mark.topology(KnownTopologyGroup.AnyProvider) -def test_id__getgrnam(client: Client, provider: GenericProvider): +def test_identity__lookup_groupname_with_getent(client: Client, provider: GenericProvider): """ :title: Resolve group by name with getent.group :setup: @@ -113,7 +113,7 @@ def test_id__getgrnam(client: Client, provider: GenericProvider): @pytest.mark.importance("critical") @pytest.mark.topology(KnownTopologyGroup.AnyProvider) -def test_id__getgrgid(client: Client, provider: GenericProvider): +def test_identity__lookup_gid_with_getent(client: Client, provider: GenericProvider): """ :title: Resolve group with by gid with getent.group :setup: @@ -146,7 +146,7 @@ def test_id__getgrgid(client: Client, provider: GenericProvider): @pytest.mark.importance("critical") @pytest.mark.topology(KnownTopologyGroup.AnyProvider) -def test_id__getent_passwd(client: Client, provider: GenericProvider): +def test_identity__lookup_user_with_getent(client: Client, provider: GenericProvider): """ :title: Resolve user with getent.passwd :setup: @@ -188,7 +188,7 @@ def test_id__getent_passwd(client: Client, provider: GenericProvider): @pytest.mark.importance("critical") @pytest.mark.topology(KnownTopologyGroup.AnyProvider) -def test_id__getent_group(client: Client, provider: GenericProvider): +def test_identity__lookup_user_by_group_with_getent(client: Client, provider: GenericProvider): """ :title: Resolve user with getent.group :setup: @@ -228,7 +228,7 @@ def test_id__getent_group(client: Client, provider: GenericProvider): @pytest.mark.importance("critical") @pytest.mark.topology(KnownTopologyGroup.AnyProvider) -def test_id__membership_by_group_name(client: Client, provider: GenericProvider): +def test_identity__lookup_group_membership_by_username_with_id(client: Client, provider: GenericProvider): """ :title: Check membership of user by group name with id :setup: @@ -261,7 +261,7 @@ def test_id__membership_by_group_name(client: Client, provider: GenericProvider) @pytest.mark.importance("critical") @pytest.mark.topology(KnownTopologyGroup.AnyProvider) -def test_id__membership_by_group_id(client: Client, provider: GenericProvider): +def test_identity__lookup_group_membership_by_group_with_id(client: Client, provider: GenericProvider): """ :title: Check membership of user by gid with id :setup: @@ -295,7 +295,7 @@ def test_id__membership_by_group_id(client: Client, provider: GenericProvider): @pytest.mark.importance("critical") @pytest.mark.topology(KnownTopologyGroup.AnyProvider) -def test_id__initgroups(client: Client, provider: GenericProvider): +def test_identity__lookup_initgroups_with_getent(client: Client, provider: GenericProvider): """ :title: Check initgroups of user :setup: @@ -334,7 +334,7 @@ def test_id__initgroups(client: Client, provider: GenericProvider): @pytest.mark.importance("critical") @pytest.mark.topology(KnownTopologyGroup.AnyProvider) -def test_id__getpwnam_fully_qualified_names(client: Client, provider: GenericProvider): +def test_identity__lookup_users_with_fully_qualified_name(client: Client, provider: GenericProvider): """ :title: Resolve user when 'use_fully_qualified_names' is 'true' :setup: @@ -377,7 +377,7 @@ def test_id__getpwnam_fully_qualified_names(client: Client, provider: GenericPro @pytest.mark.importance("critical") @pytest.mark.topology(KnownTopologyGroup.AnyProvider) -def test_id__case_insensitive(client: Client, provider: GenericProvider): +def test_identity__lookup_users_when_case_insensitive(client: Client, provider: GenericProvider): """ :title: Search user with case insensitive name when 'case_sensitive' is 'false' :setup: @@ -422,7 +422,7 @@ def test_id__case_insensitive(client: Client, provider: GenericProvider): @pytest.mark.importance("critical") @pytest.mark.topology(KnownTopologyGroup.AnyProvider) -def test_id__fq_names_case_insensitive(client: Client, provider: GenericProvider): +def test_identity__lookup_users_fully_qualified_name_and_case_insensitive(client: Client, provider: GenericProvider): """ :title: Search user with fq case insensitive name when 'case_sensitive' is 'false' and 'use_fully_qualified_names' is 'true' diff --git a/src/tests/system/tests/test_kcm.py b/src/tests/system/tests/test_kcm.py index 942e8675010..b998116f3c7 100644 --- a/src/tests/system/tests/test_kcm.py +++ b/src/tests/system/tests/test_kcm.py @@ -9,7 +9,6 @@ import time import pytest -from pytest_mh.ssh import SSHProcessError from sssd_test_framework.roles.client import Client from sssd_test_framework.roles.kdc import KDC from sssd_test_framework.topology import KnownTopology @@ -413,3 +412,4 @@ def test_kcm__simple_kinit(client: Client, kdc: KDC): with pytest.raises(SSHProcessError): krb.kinit(username, password="wrong") assert krb.klist().rc == 0, "Klist failed" + diff --git a/src/tests/system/tests/test_ldap.py b/src/tests/system/tests/test_ldap.py index d3c007e3d3e..205a0359974 100644 --- a/src/tests/system/tests/test_ldap.py +++ b/src/tests/system/tests/test_ldap.py @@ -52,3 +52,42 @@ def test_ldap__change_password(client: Client, ldap: LDAP, modify_mode: str): assert client.auth.ssh.password(user, new_pass), "Authentication with new correct password failed" assert not client.auth.ssh.password(user, old_pass), "Authentication with old incorrect password did not fail" + + +@pytest.mark.importance("high") +@pytest.mark.ldap +@pytest.mark.authentication +@pytest.mark.ticket(bz=1507035) +@pytest.mark.topology(KnownTopology.LDAP) +@pytest.mark.parametrize("method", ["su", "ssh"]) +def test_ldap__password_change(client: Client, ldap: LDAP, method: str): + """ + :title: Change password with shadow ldap password policy + :setup: + 1. Allow user to change its own password in LDAP + 2. Create LDAP user "tuser" with shadowLastChange = 0 + 3. Set ldap_pwd_policy to "shadow" + 4. Set ldap_chpass_update_last_change to "True" + 5. Start SSSD + :steps: + 1. Autheticate as "tuser" with old password + 2. Autheticate as "tuser" with new password + :expectedresults: + 1. Password was expired and new password was expected and provided + 2. Authentication with new password was successful + :customerscenario: True + """ + ldap.aci.add('(targetattr="userpassword")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///self";)') + ldap.user("tuser").add( + uid=999011, gid=999011, shadowMin=0, shadowMax=99999, shadowWarning=7, shadowLastChange=0, password="Secret123" + ) + + client.sssd.domain["ldap_pwd_policy"] = "shadow" + client.sssd.domain["ldap_chpass_update_last_change"] = "True" + client.sssd.start() + + # Password is expired, change it + assert client.auth.parametrize(method).password_expired("tuser", "Secret123", "Redhat@321") + + # Authenticate with new password + assert client.auth.parametrize(method).password("tuser", "Redhat@321") diff --git a/src/tests/system/tests/test_ldap_extra_attrs.py b/src/tests/system/tests/test_schema.py similarity index 91% rename from src/tests/system/tests/test_ldap_extra_attrs.py rename to src/tests/system/tests/test_schema.py index cf3e6ce097a..4a49e2d5def 100644 --- a/src/tests/system/tests/test_ldap_extra_attrs.py +++ b/src/tests/system/tests/test_schema.py @@ -1,5 +1,5 @@ """ -ldap_user_extra_attrs tests. +schema tests. :requirement: ldap_extra_attrs """ @@ -17,7 +17,7 @@ @pytest.mark.ticket(gh=4153, bz=1362023) @pytest.mark.topology(KnownTopologyGroup.AnyProvider) @pytest.mark.parametrize("attrs", ["mail, firstname:givenname, lastname:sn", "given_email:mail"]) -def test_ldap_extra_attrs__filled(client: Client, provider: GenericProvider, attrs: str): +def test_schema__ldap_extra_attrs_filled(client: Client, provider: GenericProvider, attrs: str): """ :title: SSSD starts correctly when ldap_user_extra_attrs is filled :setup: diff --git a/src/tests/system/tests/test_shadow.py b/src/tests/system/tests/test_shadow.py deleted file mode 100644 index 018a0f21835..00000000000 --- a/src/tests/system/tests/test_shadow.py +++ /dev/null @@ -1,50 +0,0 @@ -""" -LDAP Shadow attributes tests. - -:requirement: IDM-SSSD-REQ : LDAP Provider -""" - -from __future__ import annotations - -import pytest -from sssd_test_framework.roles.client import Client -from sssd_test_framework.roles.ldap import LDAP -from sssd_test_framework.topology import KnownTopology - - -@pytest.mark.importance("high") -@pytest.mark.schema -@pytest.mark.ticket(bz=1507035) -@pytest.mark.topology(KnownTopology.LDAP) -@pytest.mark.parametrize("method", ["su", "ssh"]) -def test_shadow__password_change(client: Client, ldap: LDAP, method: str): - """ - :title: Change password with shadow ldap password policy - :setup: - 1. Allow user to change its own password in LDAP - 2. Create LDAP user "tuser" with shadowLastChange = 0 - 3. Set ldap_pwd_policy to "shadow" - 4. Set ldap_chpass_update_last_change to "True" - 5. Start SSSD - :steps: - 1. Autheticate as "tuser" with old password - 2. Autheticate as "tuser" with new password - :expectedresults: - 1. Password was expired and new password was expected and provided - 2. Authentication with new password was successful - :customerscenario: True - """ - ldap.aci.add('(targetattr="userpassword")(version 3.0; acl "pwp test"; allow (all) userdn="ldap:///self";)') - ldap.user("tuser").add( - uid=999011, gid=999011, shadowMin=0, shadowMax=99999, shadowWarning=7, shadowLastChange=0, password="Secret123" - ) - - client.sssd.domain["ldap_pwd_policy"] = "shadow" - client.sssd.domain["ldap_chpass_update_last_change"] = "True" - client.sssd.start() - - # Password is expired, change it - assert client.auth.parametrize(method).password_expired("tuser", "Secret123", "Redhat@321") - - # Authenticate with new password - assert client.auth.parametrize(method).password("tuser", "Redhat@321") diff --git a/src/tests/system/tests/test_sssctl.py b/src/tests/system/tests/test_sssctl.py index 26cae37fddf..a3b5b473f05 100644 --- a/src/tests/system/tests/test_sssctl.py +++ b/src/tests/system/tests/test_sssctl.py @@ -2,11 +2,15 @@ SSSCTL tests. :requirement: IDM-SSSD-REQ: Status utility +:requirement: IDM-SSSD-REQ: Configuration validation """ from __future__ import annotations +import re + import pytest +from pytest_mh.ssh import SSHProcessError from sssd_test_framework.roles.client import Client from sssd_test_framework.topology import KnownTopology @@ -28,7 +32,7 @@ def test_sssctl__check_id_provider(client: Client): 2. Successfully get the error message. :customerscenario: False """ - # create sssd.conf and start the sssd, with deafult configuration with a LDAP server. + # create sssd.conf and start the sssd, with default configuration with a LDAP server. client.sssd.start() # remove id_provider parameter from domain section. @@ -71,3 +75,89 @@ def test_sssctl__check_invalid_id_provider(client: Client): "[rule/sssd_checks]: Attribute 'id_provider' in section 'domain/test' has an invalid value: invalid" in output.stdout_lines[1] ) + + +@pytest.mark.importance("high") +@pytest.mark.tools +@pytest.mark.sssctl +@pytest.mark.topology(KnownTopology.Client) +def test_sssctl__check_typo_option_name(client: Client): + """ + :title: sssctl config-check detects mistyped option name + :setup: + 1. Add wrong_option to domain section + 2. Start SSSD, without config check + :steps: + 1. Call sssctl config-check + 2. Check error message + :expectedresults: + 1. config-check detects an error in config + 2. Error message is properly set + :customerscenario: False + """ + client.sssd.common.local() + client.sssd.dom("test")["wrong_option"] = "true" + + client.sssd.start(check_config=False) + + result = client.sssctl.config_check() + assert result.rc != 0, "Config-check did not detect misconfigured config" + + pattern = re.compile(r"Attribute 'wrong_option' is not allowed.*") + assert pattern.search(result.stdout), "Wrong error message was returned" + + +@pytest.mark.importance("high") +@pytest.mark.tools +@pytest.mark.sssctl +@pytest.mark.topology(KnownTopology.Client) +def test_sssctl__check_typo_domain_name(client: Client): + """ + :title: sssctl config-check detects mistyped domain name + :setup: + 1. Create mistyped domain ("domain/") + 2. Start SSSD + :steps: + 1. Call sssctl config-check, implicitly + 2. Check error message + :expectedresults: + 1. config-check detects an error in config + 2. Error message is properly set + :customerscenario: False + """ + client.sssd.dom("")["debug_level"] = "9" + + with pytest.raises(SSHProcessError) as ex: + client.sssd.start(raise_on_error=True, check_config=True) + + assert ex.match(r"Section \[domain\/\] is not allowed. Check for typos.*"), "Wrong error message was returned" + + +@pytest.mark.importance("high") +@pytest.mark.tools +@pytest.mark.sssctl +@pytest.mark.topology(KnownTopology.Client) +def test_sssctl__check_misplaced_option(client: Client): + """ + :title: sssctl config-check detects misplaced option + :setup: + 1. In domain set "services" to "nss, pam" + 2. Start SSSD, without config check + :steps: + 1. Call sssctl config-check + 2. Check error message + :expectedresults: + 1. config-check detects an error in config + 2. Error message is properly set + :customerscenario: False + """ + client.sssd.common.local() + client.sssd.dom("test")["services"] = "nss, pam" + + client.sssd.start(check_config=False) + + result = client.sssctl.config_check() + assert result.rc != 0, "Config-check did not detect misconfigured config" + + pattern = re.compile(r".Attribute 'services' is not allowed in section .*") + assert pattern.search(result.stdout), "Wrong error message was returned" diff --git a/src/tests/system/tests/test_sssctl_config_check.py b/src/tests/system/tests/test_sssctl_config_check.py deleted file mode 100644 index b1b5faa0743..00000000000 --- a/src/tests/system/tests/test_sssctl_config_check.py +++ /dev/null @@ -1,123 +0,0 @@ -""" -sssctl config-check Test Cases - -:requirement: IDM-SSSD-REQ: Status utility -""" - -from __future__ import annotations - -import re - -import pytest -from pytest_mh.ssh import SSHProcessError -from sssd_test_framework.roles.client import Client -from sssd_test_framework.topology import KnownTopology - - -@pytest.mark.importance("high") -@pytest.mark.tools -@pytest.mark.topology(KnownTopology.Client) -def test_sssctl_config_check__typo_option_name(client: Client): - """ - :title: sssctl config-check detects mistyped option name - :setup: - 1. Add wrong_option to domain section - 2. Start SSSD, without config check - :steps: - 1. Call sssctl config-check - 2. Check error message - :expectedresults: - 1. config-check detects an error in config - 2. Error message is properly set - :customerscenario: False - """ - client.sssd.common.local() - client.sssd.dom("test")["wrong_option"] = "true" - - client.sssd.start(check_config=False) - - result = client.sssctl.config_check() - assert result.rc != 0, "Config-check did not detect misconfigured config" - - pattern = re.compile(r"Attribute 'wrong_option' is not allowed.*") - assert pattern.search(result.stdout), "Wrong error message was returned" - - -@pytest.mark.importance("high") -@pytest.mark.tools -@pytest.mark.topology(KnownTopology.Client) -def test_sssctl_config_check__typo_domain_name(client: Client): - """ - :title: sssctl config-check detects mistyped domain name - :setup: - 1. Create mistyped domain ("domain/") - 2. Start SSSD - :steps: - 1. Call sssctl config-check, implicitly - 2. Check error message - :expectedresults: - 1. config-check detects an error in config - 2. Error message is properly set - :customerscenario: False - """ - client.sssd.dom("")["debug_level"] = "9" - - with pytest.raises(SSHProcessError) as ex: - client.sssd.start(raise_on_error=True, check_config=True) - - assert ex.match(r"Section \[domain\/\] is not allowed. Check for typos.*"), "Wrong error message was returned" - - -@pytest.mark.importance("high") -@pytest.mark.tools -@pytest.mark.topology(KnownTopology.Client) -def test_sssctl_config_check__misplaced_option(client: Client): - """ - :title: sssctl config-check detects misplaced option - :setup: - 1. In domain set "services" to "nss, pam" - 2. Start SSSD, without config check - :steps: - 1. Call sssctl config-check - 2. Check error message - :expectedresults: - 1. config-check detects an error in config - 2. Error message is properly set - :customerscenario: False - """ - client.sssd.common.local() - client.sssd.dom("test")["services"] = "nss, pam" - - client.sssd.start(check_config=False) - - result = client.sssctl.config_check() - assert result.rc != 0, "Config-check did not detect misconfigured config" - - pattern = re.compile(r".Attribute 'services' is not allowed in section .*") - assert pattern.search(result.stdout), "Wrong error message was returned" - - -@pytest.mark.topology(KnownTopology.Client) -def test_sssctl_config_check__typo_option_value(client: Client): - """ - :title: sssctl config-check detects incorrect value - :setup: - 1. In local domain set "id_provider" to wrong value - 2. Apply config without config check - :steps: - 1. Call sssctl config-check - 2. Check error message - :expectedresults: - 1. config-check detects an error in config - 2. Error message is properly set - :customerscenario: False - """ - client.sssd.common.local() - client.sssd.dom("local")["id_provider"] = "wrong value" - client.sssd.config_apply(check_config=False) - - result = client.sssctl.config_check() - assert result.rc != 0, "Config-check did not detect misconfigured config" - assert ( - "Attribute 'id_provider' in section 'domain/local' has an invalid value: wrong value" in result.stdout_lines[1] - )