This commit is contained in:
Kay0u 2020-01-02 23:41:21 +08:00
parent 247411cb9f
commit 6490184333
No known key found for this signature in database
GPG key ID: 7FF262C033518333
8 changed files with 141 additions and 79 deletions

View file

@ -262,7 +262,7 @@ class BaseActionsMapParser(object):
if "authenticator" in configuration:
auth = configuration["authenticator"]
else:
auth = 'default'
auth = "default"
if not is_global and isinstance(auth, str):
# Store needed authenticator profile
if auth not in self.global_conf["authenticator"]:
@ -277,8 +277,7 @@ class BaseActionsMapParser(object):
elif is_global and isinstance(auth, dict):
if len(auth) == 0:
logger.warning(
"no profile defined in global configuration "
"for 'authenticator'"
"no profile defined in global configuration " "for 'authenticator'"
)
else:
auths = {}

View file

@ -408,7 +408,9 @@ class _ActionsMapPlugin(object):
# for additional security ?
# (An attacker could not craft such signed hashed ? (FIXME : need to make sure of this))
s_secret = self.secrets[s_id]
if profile not in request.get_cookie("session.tokens", secret=s_secret, default={}):
if profile not in request.get_cookie(
"session.tokens", secret=s_secret, default={}
):
raise HTTPUnauthorizedResponse(m18n.g("not_logged_in"))
else:
del self.secrets[s_id]
@ -670,8 +672,8 @@ class ActionsMapParser(BaseActionsMapParser):
# If several authenticator, use the default one
if isinstance(authenticator, dict):
if 'default' in authenticator:
authenticator = 'default'
if "default" in authenticator:
authenticator = "default"
else:
# TODO which one should we use?
pass

View file

@ -383,8 +383,8 @@ class ActionsMapParser(BaseActionsMapParser):
# If several authenticator, use the default one
if isinstance(authenticator, dict):
if 'default' in authenticator:
authenticator = 'default'
if "default" in authenticator:
authenticator = "default"
else:
# TODO which one should we use?
pass

View file

@ -132,15 +132,22 @@ def moulinette_cli(moulinette, mocker):
# Dirty hack needed, otherwise cookies ain't reused between request .. not
# sure why :|
import argparse
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('--debug',
action='store_true', default=False,
help="Log and print debug messages",
)
parser.add_argument(
"--debug",
action="store_true",
default=False,
help="Log and print debug messages",
)
mocker.patch("os.isatty", return_value=True)
moulinette_cli = moulinette.core.init_interface(
"cli",
actionsmap={"namespaces": ["moulitest"], "use_cache": False, "parser_kwargs": {'top_parser': parser}},
actionsmap={
"namespaces": ["moulitest"],
"use_cache": False,
"parser_kwargs": {"top_parser": parser},
},
)
mocker.stopall()
@ -183,13 +190,17 @@ def test_toml(tmp_path):
def test_ldif(tmp_path):
test_file = tmp_path / "test.txt"
from ldif import LDIFWriter
writer = LDIFWriter(open(str(test_file), 'wb'))
writer.unparse('mail=alice@example.com', {
'cn': ['Alice Alison'],
'mail': ['alice@example.com'],
'objectclass': ['top', 'person']
})
writer = LDIFWriter(open(str(test_file), "wb"))
writer.unparse(
"mail=alice@example.com",
{
"cn": ["Alice Alison"],
"mail": ["alice@example.com"],
"objectclass": ["top", "person"],
},
)
return test_file

View file

@ -69,8 +69,9 @@ def test_ask_parameter(iface, mocker):
assert arg == "a"
from moulinette.core import Moulinette18n, MoulinetteSignals
mocker.patch.object(Moulinette18n, 'n', return_value="awesome_test")
mocker.patch.object(MoulinetteSignals, 'prompt', return_value="awesome_test")
mocker.patch.object(Moulinette18n, "n", return_value="awesome_test")
mocker.patch.object(MoulinetteSignals, "prompt", return_value="awesome_test")
arg = ask("foobar", "a", None)
assert arg == "awesome_test"
@ -81,8 +82,9 @@ def test_password_parameter(iface, mocker):
assert arg == "a"
from moulinette.core import Moulinette18n, MoulinetteSignals
mocker.patch.object(Moulinette18n, 'n', return_value="awesome_test")
mocker.patch.object(MoulinetteSignals, 'prompt', return_value="awesome_test")
mocker.patch.object(Moulinette18n, "n", return_value="awesome_test")
mocker.patch.object(MoulinetteSignals, "prompt", return_value="awesome_test")
arg = ask("foobar", "a", None)
assert arg == "awesome_test"
@ -202,9 +204,13 @@ def test_extra_argument_parser_parse_args(iface, mocker):
extra_argument_parse = ExtraArgumentParser(iface)
extra_argument_parse.add_argument(GLOBAL_SECTION, "foo", {"ask": "lol"})
extra_argument_parse.add_argument(GLOBAL_SECTION, "foo2", {"ask": "lol2"})
extra_argument_parse.add_argument(GLOBAL_SECTION, "bar", {"password": "lul", "ask": "lul"})
extra_argument_parse.add_argument(
GLOBAL_SECTION, "bar", {"password": "lul", "ask": "lul"}
)
args = extra_argument_parse.parse_args(GLOBAL_SECTION, {"foo": 1, "foo2": ["a", "b", {"foobar": True}], "bar": "rab"})
args = extra_argument_parse.parse_args(
GLOBAL_SECTION, {"foo": 1, "foo2": ["a", "b", {"foobar": True}], "bar": "rab"}
)
assert "foo" in args
assert args["foo"] == 1
@ -221,21 +227,21 @@ def test_actions_map_api():
amap = ActionsMap(ActionsMapParser, use_cache=False)
assert amap.parser.global_conf['authenticate'] == "all"
assert 'default' in amap.parser.global_conf['authenticator']
assert 'yoloswag' in amap.parser.global_conf['authenticator']
assert ('GET', '/test-auth/default') in amap.parser.routes
assert ('POST', '/test-auth/subcat/post') in amap.parser.routes
assert amap.parser.global_conf["authenticate"] == "all"
assert "default" in amap.parser.global_conf["authenticator"]
assert "yoloswag" in amap.parser.global_conf["authenticator"]
assert ("GET", "/test-auth/default") in amap.parser.routes
assert ("POST", "/test-auth/subcat/post") in amap.parser.routes
amap.generate_cache()
amap = ActionsMap(ActionsMapParser, use_cache=True)
assert amap.parser.global_conf['authenticate'] == "all"
assert 'default' in amap.parser.global_conf['authenticator']
assert 'yoloswag' in amap.parser.global_conf['authenticator']
assert ('GET', '/test-auth/default') in amap.parser.routes
assert ('POST', '/test-auth/subcat/post') in amap.parser.routes
assert amap.parser.global_conf["authenticate"] == "all"
assert "default" in amap.parser.global_conf["authenticator"]
assert "yoloswag" in amap.parser.global_conf["authenticator"]
assert ("GET", "/test-auth/default") in amap.parser.routes
assert ("POST", "/test-auth/subcat/post") in amap.parser.routes
def test_actions_map_import_error(mocker):
@ -244,11 +250,12 @@ def test_actions_map_import_error(mocker):
amap = ActionsMap(ActionsMapParser)
from moulinette.core import MoulinetteLock
mocker.patch.object(MoulinetteLock, '_is_son_of', return_value=False)
mocker.patch.object(MoulinetteLock, "_is_son_of", return_value=False)
mocker.patch("__builtin__.__import__", side_effect=ImportError)
with pytest.raises(MoulinetteError) as exception:
amap.process({}, timeout=30, route=('GET', '/test-auth/none'))
amap.process({}, timeout=30, route=("GET", "/test-auth/none"))
mocker.stopall()
translation = m18n.g("error_see_log")
@ -259,29 +266,50 @@ def test_actions_map_import_error(mocker):
def test_actions_map_cli():
from moulinette.interfaces.cli import ActionsMapParser
import argparse
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument('--debug',
action='store_true', default=False,
help="Log and print debug messages",
)
amap = ActionsMap(ActionsMapParser, use_cache=False, parser_kwargs={'top_parser': parser})
assert amap.parser.global_conf['authenticate'] == "all"
assert 'default' in amap.parser.global_conf['authenticator']
assert 'yoloswag' in amap.parser.global_conf['authenticator']
assert 'testauth' in amap.parser._subparsers.choices
assert 'none' in amap.parser._subparsers.choices['testauth']._actions[1].choices
assert 'subcat' in amap.parser._subparsers.choices['testauth']._actions[1].choices
assert 'default' in amap.parser._subparsers.choices['testauth']._actions[1].choices['subcat']._actions[1].choices
parser = argparse.ArgumentParser(add_help=False)
parser.add_argument(
"--debug",
action="store_true",
default=False,
help="Log and print debug messages",
)
amap = ActionsMap(
ActionsMapParser, use_cache=False, parser_kwargs={"top_parser": parser}
)
assert amap.parser.global_conf["authenticate"] == "all"
assert "default" in amap.parser.global_conf["authenticator"]
assert "yoloswag" in amap.parser.global_conf["authenticator"]
assert "testauth" in amap.parser._subparsers.choices
assert "none" in amap.parser._subparsers.choices["testauth"]._actions[1].choices
assert "subcat" in amap.parser._subparsers.choices["testauth"]._actions[1].choices
assert (
"default"
in amap.parser._subparsers.choices["testauth"]
._actions[1]
.choices["subcat"]
._actions[1]
.choices
)
amap.generate_cache()
amap = ActionsMap(ActionsMapParser, use_cache=True, parser_kwargs={'top_parser': parser})
amap = ActionsMap(
ActionsMapParser, use_cache=True, parser_kwargs={"top_parser": parser}
)
assert amap.parser.global_conf['authenticate'] == "all"
assert 'default' in amap.parser.global_conf['authenticator']
assert 'yoloswag' in amap.parser.global_conf['authenticator']
assert 'testauth' in amap.parser._subparsers.choices
assert 'none' in amap.parser._subparsers.choices['testauth']._actions[1].choices
assert 'subcat' in amap.parser._subparsers.choices['testauth']._actions[1].choices
assert 'default' in amap.parser._subparsers.choices['testauth']._actions[1].choices['subcat']._actions[1].choices
assert amap.parser.global_conf["authenticate"] == "all"
assert "default" in amap.parser.global_conf["authenticator"]
assert "yoloswag" in amap.parser.global_conf["authenticator"]
assert "testauth" in amap.parser._subparsers.choices
assert "none" in amap.parser._subparsers.choices["testauth"]._actions[1].choices
assert "subcat" in amap.parser._subparsers.choices["testauth"]._actions[1].choices
assert (
"default"
in amap.parser._subparsers.choices["testauth"]
._actions[1]
.choices["subcat"]
._actions[1]
.choices
)

View file

@ -73,7 +73,10 @@ class TestAuthAPI:
)
def test_login_bad_password(self, moulinette_webapi):
assert self.login(moulinette_webapi, password="Bad Password", status=401).text == "Invalid password"
assert (
self.login(moulinette_webapi, password="Bad Password", status=401).text
== "Invalid password"
)
assert "session.id" not in moulinette_webapi.cookies
assert "session.tokens" not in moulinette_webapi.cookies
@ -83,7 +86,10 @@ class TestAuthAPI:
# https://security.stackexchange.com/a/58308
# https://stackoverflow.com/a/22533680
assert "CSRF protection" in self.login(moulinette_webapi, csrf=True, status=403).text
assert (
"CSRF protection"
in self.login(moulinette_webapi, csrf=True, status=403).text
)
assert not any(c.name == "session.id" for c in moulinette_webapi.cookiejar)
assert not any(c.name == "session.tokens" for c in moulinette_webapi.cookiejar)
@ -128,7 +134,9 @@ class TestAuthAPI:
assert "session.id" in moulinette_webapi.cookies
assert "session.tokens" in moulinette_webapi.cookies
cache_session_default = os.environ["MOULINETTE_CACHE_DIR"] + "/session/yoloswag/"
cache_session_default = (
os.environ["MOULINETTE_CACHE_DIR"] + "/session/yoloswag/"
)
assert moulinette_webapi.cookies["session.id"] + ".asc" in os.listdir(
cache_session_default
)
@ -153,64 +161,70 @@ class TestAuthAPI:
class TestAuthCLI:
def test_login(self, moulinette_cli, capsys, mocker):
mocker.patch('getpass.getpass', return_value='default')
moulinette_cli.run(['testauth', 'default'], output_as="plain")
mocker.patch("getpass.getpass", return_value="default")
moulinette_cli.run(["testauth", "default"], output_as="plain")
message = capsys.readouterr()
assert "some_data_from_default" in message.out
moulinette_cli.run(['testauth', 'default'], output_as="plain", password="default")
moulinette_cli.run(
["testauth", "default"], output_as="plain", password="default"
)
message = capsys.readouterr()
assert "some_data_from_default" in message.out
def test_login_bad_password(self, moulinette_cli, capsys, mocker):
with pytest.raises(MoulinetteError):
moulinette_cli.run(['testauth', 'default'], output_as="plain", password="Bad Password")
moulinette_cli.run(
["testauth", "default"], output_as="plain", password="Bad Password"
)
mocker.patch('getpass.getpass', return_value="Bad Password")
mocker.patch("getpass.getpass", return_value="Bad Password")
with pytest.raises(MoulinetteError):
moulinette_cli.run(['testauth', 'default'], output_as="plain")
moulinette_cli.run(["testauth", "default"], output_as="plain")
def test_login_wrong_profile(self, moulinette_cli, mocker):
mocker.patch('getpass.getpass', return_value='default')
mocker.patch("getpass.getpass", return_value="default")
with pytest.raises(MoulinetteError) as exception:
moulinette_cli.run(['testauth', 'other-profile'], output_as="none")
moulinette_cli.run(["testauth", "other-profile"], output_as="none")
translation = m18n.g("invalid_password")
expected_msg = translation.format()
assert expected_msg in str(exception)
with pytest.raises(MoulinetteError) as exception:
moulinette_cli.run(['testauth', 'default'], output_as="none", password="yoloswag")
moulinette_cli.run(
["testauth", "default"], output_as="none", password="yoloswag"
)
expected_msg = translation.format()
assert expected_msg in str(exception)
def test_request_no_auth_needed(self, capsys, moulinette_cli):
moulinette_cli.run(['testauth', 'none'], output_as="plain")
moulinette_cli.run(["testauth", "none"], output_as="plain")
message = capsys.readouterr()
assert "some_data_from_none" in message.out
def test_request_not_logged_only_api(self, capsys, moulinette_cli):
moulinette_cli.run(['testauth', 'only-api'], output_as="plain")
moulinette_cli.run(["testauth", "only-api"], output_as="plain")
message = capsys.readouterr()
assert "some_data_from_only_api" in message.out
def test_request_only_cli(self, capsys, moulinette_cli, mocker):
mocker.patch('getpass.getpass', return_value='default')
moulinette_cli.run(['testauth', 'only-cli'], output_as="plain")
mocker.patch("getpass.getpass", return_value="default")
moulinette_cli.run(["testauth", "only-cli"], output_as="plain")
message = capsys.readouterr()
assert "some_data_from_only_cli" in message.out
def test_request_not_logged_only_cli(self, capsys, moulinette_cli, mocker):
mocker.patch('getpass.getpass')
mocker.patch("getpass.getpass")
with pytest.raises(MoulinetteError) as exception:
moulinette_cli.run(['testauth', 'only-cli'], output_as="plain")
moulinette_cli.run(["testauth", "only-cli"], output_as="plain")
message = capsys.readouterr()
assert "some_data_from_only_cli" not in message.out

View file

@ -459,7 +459,9 @@ def test_chown_exception(test_file, mocker):
with pytest.raises(MoulinetteError) as exception:
chown(str(test_file), 1)
translation = m18n.g("error_changing_file_permissions", path=test_file, error=str(error))
translation = m18n.g(
"error_changing_file_permissions", path=test_file, error=str(error)
)
expected_msg = translation.format(path=test_file, error=str(error))
assert expected_msg in str(exception)
@ -496,7 +498,9 @@ def test_chmod_exception(test_file, mocker):
with pytest.raises(MoulinetteError) as exception:
chmod(str(test_file), 0o000)
translation = m18n.g("error_changing_file_permissions", path=test_file, error=str(error))
translation = m18n.g(
"error_changing_file_permissions", path=test_file, error=str(error)
)
expected_msg = translation.format(path=test_file, error=str(error))
assert expected_msg in str(exception)

View file

@ -107,7 +107,11 @@ def test_call_async_output_kwargs(test_file, mocker):
dirname = os.path.dirname(str(test_file))
os.mkdir(os.path.join(dirname, "teststdinfo"))
call_async_output(["cat", str(test_file)], callback, stdinfo=os.path.join(dirname, "teststdinfo", "teststdinfo"))
call_async_output(
["cat", str(test_file)],
callback,
stdinfo=os.path.join(dirname, "teststdinfo", "teststdinfo"),
)
def test_check_output(test_file):