Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
185 changes: 185 additions & 0 deletions src/tests/system/tests/test_socket.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
"""
SSSD Socket Activation Tests.

:requirement: sssd_socket
"""

from __future__ import annotations

import pytest
from sssd_test_framework.roles.client import Client
from sssd_test_framework.roles.generic import GenericProvider
from sssd_test_framework.roles.nfs import NFS
from sssd_test_framework.topology import KnownTopology


@pytest.mark.importance("high")
@pytest.mark.topology(KnownTopology.LDAP)
@pytest.mark.parametrize("responder", ["nss", "pam", "ssh"])
def test_socket__responders__socket_activation_lifecycle(client: Client, provider: GenericProvider, responder: str):
"""
:title: Socket-Activated Responder Lifecycle
:description: |
Verify that socket-activated responders:
1. Have their socket unit active
2. Have their service unit inactive initially
3. Start automatically on first client request via systemd socket activation
:setup:
1. Configure SSSD with socket activation enabled
2. Add test user to LDAP backend
:steps:
1. Verify socket unit is active and service unit is inactive
2. Trigger first request, service unit becomes active
:expectedresults:
1. Service unit is inactive before first request
2. Service unit becomes active after first request
:customerscenario: False
"""
u = provider.user("user1").add(password="Secret123")

if responder in ["pam", "ssh"]:
client.sssd.sssd["services"] = "nss"
else:
client.sssd.sssd["services"] = ""

client.sssd.restart(clean=True)
client.sssd.common.socket_responders([responder])

socket_unit = f"sssd-{responder}.socket"
service_unit = f"sssd-{responder}.service"

assert client.sssd.svc.is_active(socket_unit), f"{responder} socket should be active"
Comment on lines +40 to +51
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

This section of the test has two issues:

  1. Test Duplication: The test cases for 'pam' and 'ssh' are testing a mixed-mode scenario where 'nss' runs as a traditional service. This duplicates the scenario tested in test_socket__responders__mixed_socket_and_traditional_services for the 'ssh' responder. To improve test coverage and avoid duplication, this test should be updated to a 'pure' socket-activation scenario where 'nss' is also socket-activated when testing 'pam' or 'ssh'.

  2. Missing Assertion: The test description states that the service unit should be checked for inactivity initially, but this check is missing.

The suggested code refactors the test to address both points. It sets up a pure socket-activation environment and adds the missing check for initial service inactivity. You will also need to update the assertions at the end of the test to verify that all relevant services become active after the request.

    client.sssd.sssd["services"] = ""
    client.sssd.restart(clean=True)

    responders_to_activate = [responder]
    if responder in ["pam", "ssh"]:
        responders_to_activate.append("nss")

    client.sssd.common.socket_responders(responders_to_activate)

    service_unit = f"sssd-{responder}.service"

    for resp in responders_to_activate:
        socket_unit = f"sssd-{resp}.socket"
        resp_service_unit = f"sssd-{resp}.service"
        assert client.sssd.svc.is_active(socket_unit), f"{resp} socket should be active"
        assert not client.sssd.svc.is_active(resp_service_unit), f"{resp} service should be inactive initially"


if responder == "nss":
entry = client.tools.getent.passwd(u.name)
assert entry is not None, f"NSS provider failed for {u.name}"
assert entry.name == u.name, f"Expected user {u.name}, got {entry.name}"
elif responder == "pam":
result = client.auth.ssh.password(u.name, "Secret123")
assert result, f"PAM authentication failed for {u.name}"
elif responder == "ssh":
ssh_result = client.host.conn.run(f"sss_ssh_authorizedkeys {u.name}", raise_on_error=False)
assert ssh_result.rc == 0, f"SSH authorizedkeys lookup failed for {u.name}"

assert client.sssd.svc.is_active(service_unit), f"{responder} service should be active after request"


@pytest.mark.importance("low")
@pytest.mark.topology(KnownTopology.LDAP)
def test_socket__responders__socket_activation_lifecycle_autofs(client: Client, provider: GenericProvider, nfs: NFS):
"""
:title: Socket-Activated Autofs Responder Lifecycle
:description: |
Verify that socket-activated autofs responder:
1. Have their socket unit active
2. Have their service unit inactive initially
3. Start automatically on first client request via systemd socket activation
:setup:
1. Configure SSSD with socket activation enabled
2. Add test user and autofs maps to LDAP backend
:steps:
1. Verify socket unit is active and service unit is inactive
2. Trigger first autofs request, service unit becomes active
:expectedresults:
1. Service unit is inactive before first request
2. Service unit becomes active after first request
:customerscenario: False
"""
responder = "autofs"

nfs_export = nfs.export("export").add()
auto_master = provider.automount.map("auto.master").add()
auto_export = provider.automount.map("auto.export").add()
auto_master.key("/var/export").add(info=auto_export)
auto_export.key("export").add(info=nfs_export)

client.sssd.sssd["services"] = ""
client.sssd.restart(clean=True)
client.sssd.common.socket_responders([responder])

socket_unit = f"sssd-{responder}.socket"
service_unit = f"sssd-{responder}.service"

assert client.sssd.svc.is_active(socket_unit), f"{responder} socket should be active"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The test's description and steps state that it should verify that the service unit is inactive initially. This assertion is currently missing. Please add it to ensure the test fully validates the socket activation lifecycle.

Suggested change
assert client.sssd.svc.is_active(socket_unit), f"{responder} socket should be active"
assert client.sssd.svc.is_active(socket_unit), f"{responder} socket should be active"
assert not client.sssd.svc.is_active(service_unit), f"{responder} service should be inactive initially"


client.automount.reload()
result = client.automount.mount("/var/export/export", nfs_export)
assert result, "AUTOFS mount failed for /var/export/export"

assert client.sssd.svc.is_active(service_unit), f"{responder} service should be active after request"


@pytest.mark.importance("low")
@pytest.mark.topology(KnownTopology.LDAP)
@pytest.mark.parametrize("socket_responder", ["nss", "ssh"])
def test_socket__responders__mixed_socket_and_traditional_services(
client: Client, provider: GenericProvider, socket_responder: str
):
"""
:title: Mixed Socket-Activated and Traditional Services (NSS/SSH)
:description: |
Verify that some responders can be socket-activated while others run as traditional services
:setup:
1. Configure mixed socket-activated and traditional services
2. Add test user to LDAP backend
:steps:
1. Verify socket unit is active and service unit is inactive for socket-activated responder
2. Verify traditional responder is configured in services
3. Trigger request for socket-activated responder
4. Verify its service unit becomes active
:expectedresults:
1. Socket-activated responder is inactive before request
2. Traditional responder is configured in traditional mode
3. Request triggered for socket-activated responder
4. Socket-activated responder starts automatically on first request
:customerscenario: False
"""
u = provider.user("user1").add(password="Secret123")

if socket_responder == "nss":
traditional_responder = "ssh"
else:
traditional_responder = "nss"

client.sssd.sssd["services"] = traditional_responder
client.sssd.restart(clean=True)

client.sssd.common.socket_responders([socket_responder])

socket_unit = f"sssd-{socket_responder}.socket"
socket_service = f"sssd-{socket_responder}.service"

assert client.sssd.svc.is_active(socket_unit), f"{socket_responder} socket should be active"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The test's description and steps state that it should verify that the service unit is inactive initially for the socket-activated responder. This assertion is currently missing. Please add it to ensure the test fully validates the socket activation lifecycle.

Suggested change
assert client.sssd.svc.is_active(socket_unit), f"{socket_responder} socket should be active"
assert client.sssd.svc.is_active(socket_unit), f"{socket_responder} socket should be active"
assert not client.sssd.svc.is_active(socket_service), f"{socket_responder} service should be inactive initially"


if socket_responder == "nss":
client.tools.getent.passwd(u.name)
elif socket_responder == "ssh":
client.host.conn.run(f"sss_ssh_authorizedkeys {u.name}", raise_on_error=False)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The result of this command is not checked. The test may pass even if the sss_ssh_authorizedkeys command fails. Please capture the result and assert that its return code is 0, similar to how it's done in test_socket__responders__socket_activation_lifecycle.

Suggested change
client.host.conn.run(f"sss_ssh_authorizedkeys {u.name}", raise_on_error=False)
ssh_result = client.host.conn.run(f"sss_ssh_authorizedkeys {u.name}", raise_on_error=False)
assert ssh_result.rc == 0, f"SSH authorizedkeys lookup failed for {u.name}"


assert client.sssd.svc.is_active(socket_service), f"{socket_responder} service should be active after request"


@pytest.mark.importance("low")
@pytest.mark.topology(KnownTopology.Client)
def test_socket__responders__conflict_socket_and_traditional_config(client: Client):
"""
:title: Conflict when responder is both in sssd.conf and socket-activated
:description: |
Verify that socket activated 'sssd_nss' refuses to start when a responder is
configured both in the services line and also enabled for socket activation, as
this creates a configuration conflict.
:setup:
1. Configure SSSD with NSS responder in services line
:steps:
1. Add NSS to services line in sssd.conf and attempt to enable socket activation for NSS
:expectedresults:
1. socket_responders() raises an exception or logs error
:customerscenario: False
"""
client.sssd.common.local()

client.sssd.sssd["services"] = "nss"
client.sssd.restart(clean=True)

with pytest.raises(Exception, match="Misconfiguration found for the 'nss' responder"):
client.sssd.common.socket_responders(["nss"])
Loading