|
12 | 12 | from pytest_mh.conn import ProcessError |
13 | 13 | from pytest_mh.conn.ssh import SSHAuthenticationError |
14 | 14 | from sssd_test_framework.roles.client import Client |
| 15 | +from sssd_test_framework.roles.generic import GenericProvider |
15 | 16 | from sssd_test_framework.roles.ipa import IPA |
16 | 17 | from sssd_test_framework.roles.ldap import LDAP |
17 | 18 | from sssd_test_framework.topology import KnownTopology |
@@ -1232,3 +1233,375 @@ def test_sssctl__analyze_without_root_privileges(client: Client, ldap: LDAP): |
1232 | 1233 | assert result_user.rc == 0, "sssctl analyze call failed as user1" |
1233 | 1234 | assert result_root.stdout == result_user.stdout, "the outputs are different" |
1234 | 1235 | assert "user1" in result_user.stdout, "user1 is not in the outputs" |
| 1236 | + |
| 1237 | + |
| 1238 | +@pytest.mark.parametrize( |
| 1239 | + "case_sensitive", |
| 1240 | + [ |
| 1241 | + True, |
| 1242 | + False, |
| 1243 | + ], |
| 1244 | + ids=["case sensitive", "case insensitive"], |
| 1245 | +) |
| 1246 | +@pytest.mark.tools |
| 1247 | +@pytest.mark.topology(KnownTopology.LDAP) |
| 1248 | +def test_sssctl__user_fully_qualified_name_show(client: Client, provider: GenericProvider, case_sensitive: bool): |
| 1249 | + """ |
| 1250 | + :title: sssctl user-show displays user information |
| 1251 | + :setup: |
| 1252 | + 1. Add users to provider |
| 1253 | + 2. Configure SSSD with fqdn and case_sensitive options |
| 1254 | + 3. Start SSSD |
| 1255 | + 4. Lookup users to populate cache |
| 1256 | + :steps: |
| 1257 | + 1. Run sssctl user-show for users |
| 1258 | + 2. Run sssctl user-show for user in lower case |
| 1259 | + :expectedresults: |
| 1260 | + 1. User information is displayed correctly |
| 1261 | + 2. Lookup fails when SSSD is case_sensitive, otherwise lookup works |
| 1262 | + :customerscenario: True |
| 1263 | + """ |
| 1264 | + u1 = provider.user("user1").add() |
| 1265 | + u2 = provider.user("CamelCaseUser1").add() |
| 1266 | + client.sssd.domain["use_fully_qualified_names"] = "True" |
| 1267 | + client.sssd.domain["case_sensitive"] = str(case_sensitive) |
| 1268 | + client.sssd.start() |
| 1269 | + |
| 1270 | + user1_name = f"{u1.name}@test" |
| 1271 | + user2_name = f"{u2.name}@test" |
| 1272 | + |
| 1273 | + # Populate cache |
| 1274 | + client.tools.getent.passwd(user1_name) |
| 1275 | + client.tools.getent.passwd(user2_name) |
| 1276 | + |
| 1277 | + result = client.sssctl.user_show(user1_name) |
| 1278 | + assert result.rc == 0, f"sssctl user-show {user1_name} failed!" |
| 1279 | + assert f"Name: {user1_name}" in result.stdout, f"{user1_name} not found in sssctl output! Output: {result.stdout}" |
| 1280 | + |
| 1281 | + result = client.sssctl.user_show(user2_name) |
| 1282 | + assert result.rc == 0, f"sssctl user-show {user2_name} failed!" |
| 1283 | + expected_name = user2_name if case_sensitive else user2_name.lower() |
| 1284 | + assert ( |
| 1285 | + f"Name: {expected_name}" in result.stdout |
| 1286 | + ), f"{expected_name} is not in sssctl output! Output: {result.stdout}" |
| 1287 | + |
| 1288 | + # Test case sensitivity for lookups |
| 1289 | + lc_user_name = user2_name.lower() |
| 1290 | + result = client.sssctl.user_show(lc_user_name) |
| 1291 | + assert result.rc == 0, f"sssctl user-show {lc_user_name} failed!" |
| 1292 | + if case_sensitive: |
| 1293 | + assert " is not present in cache" in result.stdout, f"Lookup of {lc_user_name} should fail due to wrong case!" |
| 1294 | + else: |
| 1295 | + assert f"Name: {lc_user_name}" in result.stdout, f"{lc_user_name} not found in the cache!" |
| 1296 | + |
| 1297 | + |
| 1298 | +@pytest.mark.parametrize( |
| 1299 | + "case_sensitive", |
| 1300 | + [ |
| 1301 | + True, |
| 1302 | + False, |
| 1303 | + ], |
| 1304 | + ids=["case sensitive", "case insensitive"], |
| 1305 | +) |
| 1306 | +@pytest.mark.tools |
| 1307 | +@pytest.mark.topology(KnownTopology.LDAP) |
| 1308 | +def test_sssctl__user_short_name_show(client: Client, provider: GenericProvider, case_sensitive: bool): |
| 1309 | + """ |
| 1310 | + :title: sssctl user-show displays user information |
| 1311 | + :setup: |
| 1312 | + 1. Add users to provider |
| 1313 | + 2. Configure SSSD with fqdn and case_sensitive options |
| 1314 | + 3. Start SSSD |
| 1315 | + 4. Lookup users to populate cache |
| 1316 | + :steps: |
| 1317 | + 1. Run sssctl user-show for users |
| 1318 | + 2. Run sssctl user-show for user in lower case |
| 1319 | + :expectedresults: |
| 1320 | + 1. User information is displayed correctly |
| 1321 | + 2. Lookup fails when SSSD is case_sensitive, otherwise lookup works |
| 1322 | + :customerscenario: True |
| 1323 | + """ |
| 1324 | + u1 = provider.user("user1").add() |
| 1325 | + u2 = provider.user("CamelCaseUser1").add() |
| 1326 | + client.sssd.domain["use_fully_qualified_names"] = "False" |
| 1327 | + client.sssd.domain["case_sensitive"] = str(case_sensitive) |
| 1328 | + client.sssd.start() |
| 1329 | + |
| 1330 | + # Populate cache |
| 1331 | + client.tools.getent.passwd(u1.name) |
| 1332 | + client.tools.getent.passwd(u2.name) |
| 1333 | + |
| 1334 | + result = client.sssctl.user_show(u1.name) |
| 1335 | + assert result.rc == 0, f"sssctl user-show {u1.name} failed!" |
| 1336 | + assert f"Name: {u1.name}" in result.stdout, f"{u1.name} not found in sssctl output! Output: {result.stdout}" |
| 1337 | + |
| 1338 | + result = client.sssctl.user_show(u2.name) |
| 1339 | + assert result.rc == 0, f"sssctl user-show {u2.name} failed!" |
| 1340 | + expected_name = u2.name if case_sensitive else u2.name.lower() |
| 1341 | + assert ( |
| 1342 | + f"Name: {expected_name}" in result.stdout |
| 1343 | + ), f"{expected_name} not found in sssctl output! Output: {result.stdout}" |
| 1344 | + |
| 1345 | + # Test case sensitivity for lookups |
| 1346 | + lc_user_name = u2.name.lower() |
| 1347 | + result = client.sssctl.user_show(lc_user_name) |
| 1348 | + assert result.rc == 0, f"sssctl user-show {lc_user_name} failed!" |
| 1349 | + if case_sensitive: |
| 1350 | + assert " is not present in cache" in result.stdout, f"Lookup of {lc_user_name} should fail due to wrong case!" |
| 1351 | + else: |
| 1352 | + assert f"Name: {lc_user_name}" in result.stdout, f"{lc_user_name} not found in the cache!" |
| 1353 | + |
| 1354 | + |
| 1355 | +@pytest.mark.parametrize( |
| 1356 | + "case_sensitive", |
| 1357 | + [ |
| 1358 | + True, |
| 1359 | + False, |
| 1360 | + ], |
| 1361 | + ids=["case sensitive", "case insensitive"], |
| 1362 | +) |
| 1363 | +@pytest.mark.tools |
| 1364 | +@pytest.mark.topology(KnownTopology.LDAP) |
| 1365 | +def test_sssctl__group_fully_qualified_name_show(client: Client, provider: GenericProvider, case_sensitive: bool): |
| 1366 | + """ |
| 1367 | + :title: sssctl group-show displays group information |
| 1368 | + :setup: |
| 1369 | + 1. Add groups and users to provider |
| 1370 | + 2. Configure SSSD with fqdn and case_sensitive options |
| 1371 | + 3. Start SSSD |
| 1372 | + 4. Lookup groups to populate cache |
| 1373 | + :steps: |
| 1374 | + 1. Run sssctl group-show for groups |
| 1375 | + 2. Run sssctl group-show for group in lower case |
| 1376 | + :expectedresults: |
| 1377 | + 1. Group information is displayed correctly |
| 1378 | + 2. Lookup fails when SSSD is case_sensitive, otherwise lookup works |
| 1379 | + :customerscenario: True |
| 1380 | + """ |
| 1381 | + g1 = provider.group("group1").add() |
| 1382 | + cg1 = provider.group("CamelCaseGroup1").add() |
| 1383 | + client.sssd.domain["use_fully_qualified_names"] = "True" |
| 1384 | + client.sssd.domain["case_sensitive"] = str(case_sensitive) |
| 1385 | + client.sssd.start() |
| 1386 | + |
| 1387 | + group1_name = f"{g1.name}@test" |
| 1388 | + camel_group_name = f"{cg1.name}@test" |
| 1389 | + |
| 1390 | + # Populate cache |
| 1391 | + client.tools.getent.group(group1_name) |
| 1392 | + client.tools.getent.group(camel_group_name) |
| 1393 | + |
| 1394 | + result = client.sssctl.group_show(group1_name) |
| 1395 | + assert f"Name: {group1_name}" in result.stdout, f"{group1_name} not found in group-show output: {result.stdout}" |
| 1396 | + |
| 1397 | + result = client.sssctl.group_show(camel_group_name) |
| 1398 | + expected_name = camel_group_name if case_sensitive else camel_group_name.lower() |
| 1399 | + assert f"Name: {expected_name}" in result.stdout |
| 1400 | + |
| 1401 | + # Test case sensitivity for lookups |
| 1402 | + lc_group_name = camel_group_name.lower() |
| 1403 | + result = client.sssctl.group_show(lc_group_name) |
| 1404 | + if case_sensitive: |
| 1405 | + assert "is not present in cache" in result.stdout, f"Lookup of {lc_group_name} should fail due to wrong case!" |
| 1406 | + else: |
| 1407 | + assert f"Name: {lc_group_name}" in result.stdout, f"{lc_group_name} not found in the cache!" |
| 1408 | + |
| 1409 | + |
| 1410 | +@pytest.mark.parametrize( |
| 1411 | + "case_sensitive", |
| 1412 | + [ |
| 1413 | + True, |
| 1414 | + False, |
| 1415 | + ], |
| 1416 | + ids=["case sensitive", "case insensitive"], |
| 1417 | +) |
| 1418 | +@pytest.mark.tools |
| 1419 | +@pytest.mark.topology(KnownTopology.LDAP) |
| 1420 | +def test_sssctl__group_short_names_show(client: Client, provider: GenericProvider, case_sensitive: bool): |
| 1421 | + """ |
| 1422 | + :title: sssctl group-show displays group information |
| 1423 | + :setup: |
| 1424 | + 1. Add groups and users to provider |
| 1425 | + 2. Configure SSSD with fqdn and case_sensitive options |
| 1426 | + 3. Start SSSD |
| 1427 | + 4. Lookup groups to populate cache |
| 1428 | + :steps: |
| 1429 | + 1. Run sssctl group-show for groups |
| 1430 | + 2. Run sssctl group-show for group in lower case |
| 1431 | + :expectedresults: |
| 1432 | + 1. Group information is displayed correctly |
| 1433 | + 2. Lookup fails when SSSD is case_sensitive, otherwise lookup works |
| 1434 | + :customerscenario: True |
| 1435 | + """ |
| 1436 | + user = provider.user("user1").add() |
| 1437 | + camel_user = provider.user("CamelCaseUser1").add() |
| 1438 | + g1 = provider.group("group1").add().add_member(user) |
| 1439 | + cg = provider.group("CamelCaseGroup1").add().add_member(camel_user) |
| 1440 | + client.sssd.domain["use_fully_qualified_names"] = "False" |
| 1441 | + client.sssd.domain["case_sensitive"] = str(case_sensitive) |
| 1442 | + client.sssd.start() |
| 1443 | + |
| 1444 | + # Populate cache |
| 1445 | + client.tools.getent.group(g1.name) |
| 1446 | + client.tools.getent.group(cg.name) |
| 1447 | + |
| 1448 | + result = client.sssctl.group_show(g1.name) |
| 1449 | + assert f"Name: {g1.name}" in result.stdout, f"{g1.name} not fount in the output: {result.stdout}" |
| 1450 | + |
| 1451 | + result = client.sssctl.group_show(cg.name) |
| 1452 | + expected_name = cg.name if case_sensitive else cg.name.lower() |
| 1453 | + assert f"Name: {expected_name}" in result.stdout, f"{expected_name} not fount in the output: {result.stdout}" |
| 1454 | + |
| 1455 | + # Test case sensitivity for lookups |
| 1456 | + lc_group_name = cg.name.lower() |
| 1457 | + result = client.sssctl.group_show(lc_group_name) |
| 1458 | + if case_sensitive: |
| 1459 | + assert "is not present in cache" in result.stdout, f"Lookup of {lc_group_name} should fail due to wrong case!" |
| 1460 | + else: |
| 1461 | + assert f"Name: {lc_group_name}" in result.stdout, f"{lc_group_name} not found in the cache!" |
| 1462 | + |
| 1463 | + |
| 1464 | +@pytest.mark.parametrize( |
| 1465 | + "component", |
| 1466 | + ["sssd", "nss", "pam", "domain/test"], |
| 1467 | +) |
| 1468 | +@pytest.mark.tools |
| 1469 | +@pytest.mark.topology(KnownTopology.LDAP) |
| 1470 | +def test_sssctl__debug_level_component(client: Client, provider: GenericProvider, component: str): |
| 1471 | + """ |
| 1472 | + :title: sssctl debug-level sets and gets debug levels |
| 1473 | + :setup: |
| 1474 | + 1. Start SSSD |
| 1475 | + :steps: |
| 1476 | + 1. Set debug level for all components |
| 1477 | + 2. Get debug level for all components and verify |
| 1478 | + 3. Set debug level for one component and verify |
| 1479 | + :expectedresults: |
| 1480 | + 1. Command succeeds |
| 1481 | + 2. Debug levels are set for all components |
| 1482 | + 3. Debug level has changed just for one component |
| 1483 | + :customerscenario: True |
| 1484 | + """ |
| 1485 | + # make sure we start from a known state |
| 1486 | + client.sssd.domain["debug_level"] = "0" |
| 1487 | + client.sssd.sssd["debug_level"] = "0" |
| 1488 | + client.sssd.nss["debug_level"] = "0" |
| 1489 | + client.sssd.pam["debug_level"] = "0" |
| 1490 | + client.sssd.start() |
| 1491 | + |
| 1492 | + client.sssctl.debug_level(level="0x00F0") |
| 1493 | + result = client.sssctl.debug_level() |
| 1494 | + other_components = [s.split()[0] for s in result.stdout.splitlines() if not s.startswith(component)] |
| 1495 | + |
| 1496 | + for item in [component] + other_components: |
| 1497 | + assert re.search(f"^{item}\\s+0x00f0", result.stdout, re.MULTILINE), f"Debug level for [{item}] is not set" |
| 1498 | + |
| 1499 | + # The --sssd option is not supported by sssctl.debug_level() at the moment |
| 1500 | + component_option = "--domain test" if component == "domain/test" else f"--{component}" |
| 1501 | + client.host.conn.exec(f"sssctl debug-level {component_option} 0x0270".split()) |
| 1502 | + |
| 1503 | + result = client.sssctl.debug_level() |
| 1504 | + match = re.search(f"^{component}\\s+(0x[0-9a-f]+)", result.stdout, re.MULTILINE) |
| 1505 | + assert match is not None, f"Debug level of [{component}] not found in output: {result.stdout}" |
| 1506 | + assert match.group(1) == "0x0270", f"Debug level for [{component}] is {match.group(1)} but it should be 0x0270" |
| 1507 | + for item in other_components: |
| 1508 | + match = re.search(f"^{item}\\s+(0x[0-9a-f]+)", result.stdout, re.MULTILINE) |
| 1509 | + assert match is not None, f"Debug level of [{item}] not found in output: {result.stdout}" |
| 1510 | + assert match.group(1) == "0x00f0", f"Debug level for [{item}] is {match.group(1)} but it should be 0x00f0" |
| 1511 | + |
| 1512 | + |
| 1513 | +@pytest.mark.tools |
| 1514 | +@pytest.mark.topology(KnownTopology.LDAP) |
| 1515 | +def test_sssctl__debug_level_negative(client: Client, provider: GenericProvider): |
| 1516 | + """ |
| 1517 | + :title: sssctl debug-level gives proper error message for non existing services |
| 1518 | + :setup: |
| 1519 | + 1. Start SSSD |
| 1520 | + :steps: |
| 1521 | + 1. Try to get debug level for non existing domain |
| 1522 | + 2. Try to set debug level for non existing domain |
| 1523 | + 3. Try to get debug level for an unreachable service |
| 1524 | + :expectedresults: |
| 1525 | + 1. Command fails with proper message |
| 1526 | + 2. Command fails with an empty message |
| 1527 | + 3. Command fails with "Unreachable service" |
| 1528 | + :customerscenario: True |
| 1529 | + """ |
| 1530 | + client.sssd.start() |
| 1531 | + |
| 1532 | + result = client.host.conn.exec(["sssctl", "debug-level", "--domain=FAKE"], raise_on_error=False) |
| 1533 | + assert result.rc != 0, "The command `sssctl debug-level FAKE` must fail!" |
| 1534 | + assert "Unknown domain" in result.stdout, "sssctl debug-level for FAKE domain must report 'Unknown domain'!" |
| 1535 | + |
| 1536 | + result = client.host.conn.exec(["sssctl", "debug-level", "--domain=FAKE", "8"], raise_on_error=False) |
| 1537 | + assert result.rc != 0, "The command `sssctl debug-level FAKE 8` must fail!" |
| 1538 | + assert result.stdout.strip() == "" |
| 1539 | + |
| 1540 | + # For unreachable service, pac is a good candidate if not using IPA |
| 1541 | + result = client.host.conn.exec(["sssctl", "debug-level", "--pac"], raise_on_error=False) |
| 1542 | + assert result.rc != 0, "sssctl debug-level must return an error for unreachable service!" |
| 1543 | + assert "Unreachable service" in result.stdout, f"Wrong error message in output: {result.stdout}" |
| 1544 | + |
| 1545 | + |
| 1546 | +@pytest.mark.tools |
| 1547 | +@pytest.mark.topology(KnownTopology.LDAP) |
| 1548 | +def test_sssctl__cache_expire_missing_entry(client: Client): |
| 1549 | + """ |
| 1550 | + :title: sssctl cache-expire fails for non-existent entries |
| 1551 | + :setup: |
| 1552 | + 1. Start SSSD |
| 1553 | + :steps: |
| 1554 | + 1. Run sssctl cache-expire for non-existent user |
| 1555 | + 2. Run sssctl cache-expire for non-existent group |
| 1556 | + 3. Run sssctl cache-expire for non-existent user in non-existent domain |
| 1557 | + 4. Run sssctl cache-expire for non-existent group in non-existent domain |
| 1558 | + :expectedresults: |
| 1559 | + 1. Command fails for non-existent user |
| 1560 | + 2. Command fails for non-existent group |
| 1561 | + 3. Command fails for non-existent user in non-existent domain |
| 1562 | + 4. Command fails for non-existent group in non-existent domain |
| 1563 | + :customerscenario: True |
| 1564 | + """ |
| 1565 | + client.sssd.start() |
| 1566 | + |
| 1567 | + result = client.host.conn.run("sssctl cache-expire -u non-existing", raise_on_error=False) |
| 1568 | + assert result.rc != 0, "sssctl cache-expire must return error for non-existing user!" |
| 1569 | + |
| 1570 | + result = client.host.conn.run("sssctl cache-expire -g non-existing", raise_on_error=False) |
| 1571 | + assert result.rc != 0, "sssctl cache-expire must return error for non-existing group!" |
| 1572 | + |
| 1573 | + result = client.host.conn.run("sssctl cache-expire -d non-existing -u dummy", raise_on_error=False) |
| 1574 | + assert result.rc != 0, "sssctl cache-expire must return error for non-existing user and domain!" |
| 1575 | + |
| 1576 | + result = client.host.conn.run("sssctl cache-expire -d non-existing -g dummy", raise_on_error=False) |
| 1577 | + assert result.rc != 0, "sssctl cache-expire must return error for non-existing group and domain!" |
| 1578 | + |
| 1579 | + |
| 1580 | +@pytest.mark.tools |
| 1581 | +@pytest.mark.topology(KnownTopology.Client) |
| 1582 | +def test_sssctl__config_check_snippets_only(client: Client): |
| 1583 | + """ |
| 1584 | + :title: sssctl config-check works with only snippet files |
| 1585 | + :setup: |
| 1586 | + 1. Ensure no main sssd.conf exists |
| 1587 | + 2. Create a config snippet file |
| 1588 | + :steps: |
| 1589 | + 1. Run sssctl config-check |
| 1590 | + :expectedresults: |
| 1591 | + 1. Command succeeds and prints the parsed config |
| 1592 | + :customerscenario: True |
| 1593 | + """ |
| 1594 | + |
| 1595 | + client.fs.rm("/etc/sssd/sssd.conf") |
| 1596 | + client.fs.rm("/etc/sssd/conf.d/*") |
| 1597 | + |
| 1598 | + client.fs.write( |
| 1599 | + "/etc/sssd/conf.d/test.conf", "[sssd]\nservices = nss, pam, ssh\n", mode="600", user="root", group="root" |
| 1600 | + ) |
| 1601 | + |
| 1602 | + result = client.sssctl.config_check() |
| 1603 | + assert result.rc == 0, "sssctl config-check must succeed for snippet only configuration!" |
| 1604 | + assert ( |
| 1605 | + "There is no configuration" not in result.stdout |
| 1606 | + ), "sssctl config-check must not complain about missing configuration!" |
| 1607 | + assert "Used configuration snippet files: 1" in result.stdout, "sssctl config-check must show 1 config snippet!" |
0 commit comments