implement support of unix socket for server

This feature can be used for unauthorized access to apis - e.g. for
reporting service if it is run on the same machine. Since now it becomes
recommended way for the interprocess communication, thus some options
(e.g. creating user with as-service flag) are no longer available now
This commit is contained in:
2022-11-29 01:18:01 +02:00
parent 4811dec759
commit 0161617e36
24 changed files with 247 additions and 134 deletions

View File

@ -1,17 +1,16 @@
import pytest
from collections import namedtuple
_passwd = namedtuple("passwd", ["pw_dir"])
from unittest.mock import MagicMock
@pytest.fixture
def passwd() -> _passwd:
def passwd() -> MagicMock:
"""
get passwd structure for the user
Returns:
_passwd: passwd structure test instance
MagicMock: passwd structure test instance
"""
return _passwd("home")
passwd = MagicMock()
passwd.pw_dir = "home"
return passwd

View File

@ -31,6 +31,7 @@ def _default_args(args: argparse.Namespace) -> argparse.Namespace:
args.sign_key = "key"
args.sign_target = [SignSettings.Packages]
args.web_port = 8080
args.web_unix_socket = Path("/var/lib/ahriman/ahriman-web.sock")
return args
@ -91,6 +92,7 @@ def test_configuration_create_ahriman(args: argparse.Namespace, configuration: C
" ".join([target.name.lower() for target in args.sign_target])),
MockCall(Configuration.section_name("sign", "x86_64"), "key", args.sign_key),
MockCall(Configuration.section_name("web", "x86_64"), "port", str(args.web_port)),
MockCall(Configuration.section_name("web", "x86_64"), "unix_socket", str(args.web_unix_socket)),
])
write_mock.assert_called_once_with(pytest.helpers.anyvar(int))

View File

@ -26,7 +26,6 @@ def _default_args(args: argparse.Namespace) -> argparse.Namespace:
"""
args.username = "user"
args.action = Action.Update
args.as_service = False
args.exit_code = False
args.password = "pa55w0rd"
args.role = UserAccess.Reporter
@ -73,33 +72,8 @@ def test_run_empty_salt(args: argparse.Namespace, configuration: Configuration,
Users.run(args, "x86_64", configuration, report=False, unsafe=False)
get_auth_configuration_mock.assert_called_once_with(configuration.include)
create_configuration_mock.assert_called_once_with(pytest.helpers.anyvar(int), pytest.helpers.anyvar(int),
pytest.helpers.anyvar(int), args.as_service, args.secure)
create_user_mock.assert_called_once_with(args)
get_salt_mock.assert_called_once_with(configuration)
update_mock.assert_called_once_with(user)
def test_run_service_user(args: argparse.Namespace, configuration: Configuration, database: SQLite,
mocker: MockerFixture) -> None:
"""
must create configuration if as service argument is provided
"""
args = _default_args(args)
args.as_service = True
user = User(username=args.username, password=args.password, access=args.role)
mocker.patch("ahriman.core.database.SQLite.load", return_value=database)
mocker.patch("ahriman.models.user.User.hash_password", return_value=user)
get_auth_configuration_mock = mocker.patch("ahriman.application.handlers.Users.configuration_get")
create_configuration_mock = mocker.patch("ahriman.application.handlers.Users.configuration_create")
create_user_mock = mocker.patch("ahriman.application.handlers.Users.user_create", return_value=user)
get_salt_mock = mocker.patch("ahriman.application.handlers.Users.get_salt", return_value=("salt", "salt"))
update_mock = mocker.patch("ahriman.core.database.SQLite.user_update")
Users.run(args, "x86_64", configuration, report=False, unsafe=False)
get_auth_configuration_mock.assert_called_once_with(configuration.include)
create_configuration_mock.assert_called_once_with(pytest.helpers.anyvar(int), pytest.helpers.anyvar(int),
pytest.helpers.anyvar(int), args.as_service, args.secure)
create_configuration_mock.assert_called_once_with(
pytest.helpers.anyvar(int), pytest.helpers.anyvar(int), args.secure)
create_user_mock.assert_called_once_with(args)
get_salt_mock.assert_called_once_with(configuration)
update_mock.assert_called_once_with(user)
@ -151,7 +125,7 @@ def test_run_remove(args: argparse.Namespace, configuration: Configuration, data
remove_mock.assert_called_once_with(args.username)
def test_configuration_create(configuration: Configuration, user: User, mocker: MockerFixture) -> None:
def test_configuration_create(configuration: Configuration, mocker: MockerFixture) -> None:
"""
must correctly create configuration file
"""
@ -159,26 +133,11 @@ def test_configuration_create(configuration: Configuration, user: User, mocker:
set_mock = mocker.patch("ahriman.core.configuration.Configuration.set_option")
write_mock = mocker.patch("ahriman.application.handlers.Users.configuration_write")
Users.configuration_create(configuration, user, "salt", False, False)
Users.configuration_create(configuration, "salt", False)
set_mock.assert_called_once_with("auth", "salt", pytest.helpers.anyvar(int))
write_mock.assert_called_once_with(configuration, False)
def test_configuration_create_with_plain_password(configuration: Configuration, user: User,
mocker: MockerFixture) -> None:
"""
must set plain text password and user for the service
"""
mocker.patch("pathlib.Path.open")
Users.configuration_create(configuration, user, "salt", True, False)
generated = User.from_option(user.username, user.password).hash_password("salt")
service = User.from_option(configuration.get("web", "username"), configuration.get("web", "password"))
assert generated.username == service.username
assert generated.check_credentials(service.password, configuration.get("auth", "salt"))
def test_configuration_get(mocker: MockerFixture) -> None:
"""
must load configuration from filesystem