mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Reverting 'Two-factor authentication' support as it cause OSX and docker build failures.
This reverts commit 787a441343.
This commit is contained in:
@@ -1,154 +0,0 @@
|
||||
##############################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##############################################################################
|
||||
from pgadmin.authenticate.mfa import mfa_enabled
|
||||
import config
|
||||
|
||||
|
||||
__MFA_ENABLED = 'MFA Enabled'
|
||||
__MFA_DISABLED = 'MFA Disabled'
|
||||
TEST_UTILS_AUTH_PKG = 'tests.utils'
|
||||
|
||||
|
||||
def __mfa_is_enabled():
|
||||
return __MFA_ENABLED
|
||||
|
||||
|
||||
def __mfa_is_disabled():
|
||||
return __MFA_DISABLED
|
||||
|
||||
|
||||
def check_mfa_enabled(test):
|
||||
config.MFA_ENABLED = test.enabled
|
||||
config.MFA_SUPPORTED_METHODS = test.supported_list
|
||||
|
||||
if mfa_enabled(__mfa_is_enabled, __mfa_is_disabled) != test.expected:
|
||||
test.fail(test.fail_msg)
|
||||
|
||||
|
||||
def log_message_in_init_app(test):
|
||||
import types
|
||||
from unittest.mock import patch
|
||||
from .. import init_app
|
||||
from .utils import test_create_dummy_app
|
||||
|
||||
auth_method_msg = "'xyz' is not a valid multi-factor authentication method"
|
||||
disabled_msg = \
|
||||
"No valid multi-factor authentication found, hence - disabling it."
|
||||
warning_invalid_auth_found = False
|
||||
warning_disable_auth = False
|
||||
|
||||
dummy_app = test_create_dummy_app(test.name)
|
||||
|
||||
def _log_warning_msg(_msg):
|
||||
nonlocal warning_invalid_auth_found
|
||||
nonlocal warning_disable_auth
|
||||
|
||||
if auth_method_msg == _msg:
|
||||
warning_invalid_auth_found = True
|
||||
return
|
||||
|
||||
if _msg == disabled_msg:
|
||||
warning_disable_auth = True
|
||||
|
||||
with patch.object(
|
||||
dummy_app.logger,
|
||||
'warning',
|
||||
new=_log_warning_msg
|
||||
):
|
||||
config.MFA_ENABLED = True
|
||||
config.MFA_SUPPORTED_METHODS = test.supported_list
|
||||
init_app(dummy_app)
|
||||
|
||||
if warning_invalid_auth_found is not test.warning_invalid_auth_found \
|
||||
or warning_disable_auth is not test.warning_disable_auth:
|
||||
test.fail(test.fail_msg)
|
||||
test.fail()
|
||||
|
||||
|
||||
config_scenarios = [
|
||||
(
|
||||
"Check MFA enabled with no authenticators?",
|
||||
dict(
|
||||
check=check_mfa_enabled, enabled=True, supported_list=list(),
|
||||
expected=__MFA_DISABLED,
|
||||
fail_msg="MFA is enabled with no authenticators, but - "
|
||||
"'execute_if_disabled' function is not called."
|
||||
),
|
||||
),
|
||||
(
|
||||
"Check MFA enabled?",
|
||||
dict(
|
||||
check=check_mfa_enabled, enabled=True,
|
||||
supported_list=[TEST_UTILS_AUTH_PKG], expected=__MFA_ENABLED,
|
||||
fail_msg="MFA is enable, but - 'execute_if_enabled' function "
|
||||
"is not called."
|
||||
),
|
||||
),
|
||||
(
|
||||
"Check MFA disabled check functionality works?",
|
||||
dict(
|
||||
check=check_mfa_enabled, enabled=False,
|
||||
supported_list=list(),
|
||||
expected=__MFA_DISABLED,
|
||||
fail_msg="MFA is disabled, but - 'execute_if_enabled' function "
|
||||
"is called."
|
||||
),
|
||||
),
|
||||
(
|
||||
"Check MFA in the supported MFA LIST is part of the registered one",
|
||||
dict(
|
||||
check=check_mfa_enabled, enabled=True,
|
||||
supported_list=["not-in-list"],
|
||||
expected=__MFA_DISABLED,
|
||||
fail_msg="MFA is enabled with invalid authenticators, but - "
|
||||
"'execute_if_enabled' function is called"
|
||||
),
|
||||
),
|
||||
(
|
||||
"Check warning message with invalid method appended during "
|
||||
"init_app(...)",
|
||||
dict(
|
||||
check=log_message_in_init_app,
|
||||
supported_list=["xyz", TEST_UTILS_AUTH_PKG],
|
||||
name="warning_app_having_invalid_method",
|
||||
warning_invalid_auth_found=True, warning_disable_auth=False,
|
||||
fail_msg="Warning for invalid auth is not found",
|
||||
),
|
||||
),
|
||||
(
|
||||
"Check warning message with invalid method during "
|
||||
"init_app(...) ",
|
||||
dict(
|
||||
check=log_message_in_init_app, supported_list=["xyz"],
|
||||
name="warning_app_with_invalid_method",
|
||||
warning_invalid_auth_found=False, warning_disable_auth=True,
|
||||
fail_msg="Warning for invalid auth is not found",
|
||||
),
|
||||
),
|
||||
(
|
||||
"Check warning message when empty supported mfa list during "
|
||||
"init_app(...)",
|
||||
dict(
|
||||
check=log_message_in_init_app, supported_list=[""],
|
||||
name="warning_app_with_empty_supported_list",
|
||||
warning_invalid_auth_found=False, warning_disable_auth=True,
|
||||
fail_msg="Warning not found with empty supported mfa methods",
|
||||
),
|
||||
),
|
||||
(
|
||||
"No warning message should found with valid configurations during "
|
||||
"init_app(...)",
|
||||
dict(
|
||||
check=log_message_in_init_app, name="no_warning_app",
|
||||
supported_list=[TEST_UTILS_AUTH_PKG],
|
||||
warning_invalid_auth_found=False, warning_disable_auth=False,
|
||||
fail_msg="Warning found with valid configure",
|
||||
),
|
||||
),
|
||||
]
|
||||
@@ -1,56 +0,0 @@
|
||||
##############################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##############################################################################
|
||||
from pgadmin.utils.route import BaseTestGenerator
|
||||
import config
|
||||
from .test_config import config_scenarios
|
||||
from .test_user_execution import user_execution_scenarios
|
||||
from .test_mfa_view import validation_view_scenarios
|
||||
from .utils import init_dummy_auth_class
|
||||
|
||||
|
||||
test_scenarios = list()
|
||||
test_scenarios += config_scenarios
|
||||
test_scenarios += user_execution_scenarios
|
||||
test_scenarios += validation_view_scenarios
|
||||
|
||||
|
||||
class TestMFATests(BaseTestGenerator):
|
||||
|
||||
scenarios = test_scenarios
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
config.MFA_ENABLED = True
|
||||
init_dummy_auth_class()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
config.MFA_ENABLED = False
|
||||
config.MFA_SUPPORTED_METHODS = []
|
||||
|
||||
def setUp(self):
|
||||
config.MFA_SUPPORTED_METHODS = ['tests.utils']
|
||||
|
||||
start = getattr(self, 'start', None)
|
||||
if start is not None:
|
||||
start(self)
|
||||
|
||||
super(BaseTestGenerator, self).setUp()
|
||||
|
||||
def tearDown(self):
|
||||
|
||||
finish = getattr(self, 'finish', None)
|
||||
if finish is not None:
|
||||
finish(self)
|
||||
|
||||
config.MFA_SUPPORTED_METHODS = []
|
||||
super(BaseTestGenerator, self).tearDown()
|
||||
|
||||
def runTest(self):
|
||||
self.check(self)
|
||||
@@ -1,66 +0,0 @@
|
||||
##############################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##############################################################################
|
||||
from unittest.mock import patch
|
||||
import config
|
||||
|
||||
from .utils import setup_mfa_app, MockCurrentUserId, MockUserMFA
|
||||
from pgadmin.authenticate.mfa.utils import ValidationException
|
||||
|
||||
|
||||
__MFA_PACKAGE = '.'.join((__package__.split('.'))[:-1])
|
||||
__AUTH_PACKAGE = '.'.join((__package__.split('.'))[:-2])
|
||||
|
||||
|
||||
def check_validation_view_content(test):
|
||||
user_mfa_test_data = [
|
||||
MockUserMFA(1, "dummy", ""),
|
||||
MockUserMFA(1, "no-present-in-list", None),
|
||||
]
|
||||
|
||||
def mock_log_exception(ex):
|
||||
test.assertTrue(type(ex) == ValidationException)
|
||||
|
||||
with patch(
|
||||
__MFA_PACKAGE + ".utils.current_user", return_value=MockCurrentUserId()
|
||||
):
|
||||
with patch(__MFA_PACKAGE + ".utils.UserMFA") as mock_user_mfa:
|
||||
with test.app.test_request_context():
|
||||
with patch("flask.current_app") as mock_current_app:
|
||||
mock_user_mfa.query.filter_by.return_value \
|
||||
.all.return_value = user_mfa_test_data
|
||||
mock_current_app.logger.exception = mock_log_exception
|
||||
|
||||
with patch(__AUTH_PACKAGE + ".session") as mock_session:
|
||||
session = {
|
||||
'auth_source_manager': {
|
||||
'current_source': getattr(
|
||||
test, 'auth_method', 'internal'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
mock_session.__getitem__.side_effect = \
|
||||
session.__getitem__
|
||||
|
||||
response = test.tester.get("/mfa/validate")
|
||||
|
||||
test.assertEquals(response.status_code, 200)
|
||||
test.assertEquals(
|
||||
response.headers["Content-Type"], "text/html; charset=utf-8"
|
||||
)
|
||||
# test.assertTrue('Dummy' in response.data.decode('utf8'))
|
||||
# End of test case - check_validation_view_content
|
||||
|
||||
|
||||
validation_view_scenarios = [
|
||||
(
|
||||
"Validation view of a MFA method should return a HTML tags",
|
||||
dict(start=setup_mfa_app, check=check_validation_view_content),
|
||||
),
|
||||
]
|
||||
@@ -1,125 +0,0 @@
|
||||
##############################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##############################################################################
|
||||
from unittest.mock import patch
|
||||
import config
|
||||
from pgadmin.authenticate.mfa.utils import \
|
||||
mfa_user_force_registration_required
|
||||
from pgadmin.authenticate.mfa.utils import mfa_user_registered, \
|
||||
user_supported_mfa_methods
|
||||
from .utils import MockUserMFA, MockCurrentUserId
|
||||
|
||||
|
||||
__MFA_PACKAGE = '.'.join((__package__.split('.'))[:-1])
|
||||
|
||||
|
||||
def __return_true():
|
||||
return True
|
||||
|
||||
|
||||
def __return_false():
|
||||
return False
|
||||
|
||||
|
||||
def check_user_registered(test):
|
||||
|
||||
user_mfa_test_data = [
|
||||
MockUserMFA(1, "dummy", "Hello guys"),
|
||||
MockUserMFA(1, "no-present-in-list", None),
|
||||
]
|
||||
|
||||
with patch(
|
||||
__MFA_PACKAGE + ".utils.current_user", return_value=MockCurrentUserId()
|
||||
):
|
||||
with patch(__MFA_PACKAGE + ".utils.UserMFA") as mock_user_mfa:
|
||||
mock_user_mfa.query.filter_by.return_value.all.return_value = \
|
||||
user_mfa_test_data
|
||||
|
||||
ret = mfa_user_registered(__return_true, __return_false)
|
||||
|
||||
if ret is None:
|
||||
test.fail(
|
||||
"User registration check has not called either "
|
||||
"'is_registered' or 'is_not_registered' function"
|
||||
)
|
||||
|
||||
if ret is False:
|
||||
test.fail(
|
||||
"Not expected to be called 'is_not_registered' function "
|
||||
"as 'dummy' is in the supported MFA methods"
|
||||
)
|
||||
|
||||
methods = user_supported_mfa_methods()
|
||||
if "dummy" not in methods:
|
||||
test.fail(
|
||||
"User registration methods are not valid: {}".format(
|
||||
methods
|
||||
)
|
||||
)
|
||||
|
||||
# Removed the 'dummy' from the user's registered MFA list
|
||||
user_mfa_test_data.pop(0)
|
||||
ret = mfa_user_registered(__return_true, __return_false)
|
||||
|
||||
if ret is None:
|
||||
test.fail(
|
||||
"User registration check has not called either "
|
||||
"'is_registered' or 'is_not_registered' function"
|
||||
)
|
||||
|
||||
if ret is True:
|
||||
test.fail(
|
||||
"Not expected to be called 'is_registered' function as "
|
||||
"'not-present-in-list' is not a valid multi-factor "
|
||||
"authentication method"
|
||||
)
|
||||
|
||||
# End of test case - check_user_registered
|
||||
|
||||
|
||||
def check_force_registration_required(test):
|
||||
|
||||
if mfa_user_force_registration_required(
|
||||
__return_false, __return_true
|
||||
) is None:
|
||||
test.fail(
|
||||
"User registration check did not call either register or "
|
||||
"do_not_register function"
|
||||
)
|
||||
|
||||
config.MFA_FORCE_REGISTRATION = False
|
||||
if mfa_user_force_registration_required(
|
||||
__return_true, __return_false
|
||||
) is True:
|
||||
test.fail(
|
||||
"User registration function should not be called, when "
|
||||
"config.MFA_FORCE_REGISTRATION is True"
|
||||
)
|
||||
|
||||
config.MFA_FORCE_REGISTRATION = True
|
||||
if mfa_user_force_registration_required(
|
||||
__return_true, __return_false
|
||||
) is False:
|
||||
test.fail(
|
||||
"'do_not_registration' function should not be called, when "
|
||||
"config.MFA_FORCE_REGISTRATION is True"
|
||||
)
|
||||
|
||||
# End of test case - check_force_registration_required
|
||||
|
||||
|
||||
user_execution_scenarios = [
|
||||
(
|
||||
"Check user is registered to do MFA",
|
||||
dict(check=check_user_registered),
|
||||
),
|
||||
(
|
||||
"Require the forcefull registration for MFA?",
|
||||
dict(check=check_force_registration_required),
|
||||
),
|
||||
]
|
||||
@@ -1,111 +0,0 @@
|
||||
##############################################################################
|
||||
#
|
||||
# pgAdmin 4 - PostgreSQL Tools
|
||||
#
|
||||
# Copyright (C) 2013 - 2021, The pgAdmin Development Team
|
||||
# This software is released under the PostgreSQL Licence
|
||||
#
|
||||
##############################################################################
|
||||
import types
|
||||
|
||||
from flask import Flask, Response
|
||||
import config
|
||||
|
||||
from pgadmin.authenticate.mfa import init_app as mfa_init_app
|
||||
|
||||
|
||||
def init_dummy_auth_class():
|
||||
from pgadmin.authenticate.mfa.registry import BaseMFAuth
|
||||
|
||||
class DummyAuth(BaseMFAuth): # NOSONAR - S5603
|
||||
"""
|
||||
A dummy authentication for testing the registry ability of adding
|
||||
'dummy' authentication method.
|
||||
|
||||
Declaration is enough to use this class, we don't have to use it
|
||||
directly, as it will be initialized automatically by the registry, and
|
||||
ready to use.
|
||||
"""
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
return "dummy"
|
||||
|
||||
@property
|
||||
def label(self):
|
||||
return "Dummy"
|
||||
|
||||
def validate(self, **kwargs):
|
||||
return true
|
||||
|
||||
def validation_view(self):
|
||||
return "View"
|
||||
|
||||
def registration_view(self):
|
||||
return "Registration"
|
||||
|
||||
def register_url_endpoints(self, blueprint):
|
||||
print('Initialize the end-points for dummy auth')
|
||||
|
||||
# FPSONAR_OFF
|
||||
|
||||
|
||||
def test_create_dummy_app(name=__name__):
|
||||
import os
|
||||
import pgadmin
|
||||
from pgadmin.misc.themes import themes
|
||||
|
||||
def index():
|
||||
return Response("<html><body>logged in</body></html>")
|
||||
|
||||
template_folder = os.path.join(
|
||||
os.path.dirname(os.path.realpath(pgadmin.__file__)), 'templates'
|
||||
)
|
||||
app = Flask(name, template_folder=template_folder)
|
||||
config.MFA_ENABLED = True
|
||||
config.MFA_SUPPORTED_METHODS = ['tests.utils']
|
||||
app.config.from_object(config)
|
||||
app.config.update(dict(LOGIN_DISABLED=True))
|
||||
app.add_url_rule("/", "index", index, methods=("GET",))
|
||||
app.add_url_rule(
|
||||
"/favicon.ico", "redirects.favicon", index, methods=("GET",)
|
||||
)
|
||||
app.add_url_rule("/browser", "browser.index", index, methods=("GET",))
|
||||
app.add_url_rule("/tools", "tools.index", index, methods=("GET",))
|
||||
app.add_url_rule(
|
||||
"/users", "user_management.index", index, methods=("GET",)
|
||||
)
|
||||
app.add_url_rule(
|
||||
"/login", "security.logout", index, methods=("GET",)
|
||||
)
|
||||
app.add_url_rule(
|
||||
"/kerberos_logout", "authenticate.kerberos_logout", index,
|
||||
methods=("GET",)
|
||||
)
|
||||
|
||||
def __dummy_logout_hook(self, blueprint):
|
||||
pass # We don't need the logout url when dummy auth is enabled.
|
||||
|
||||
app.register_logout_hook = types.MethodType(__dummy_logout_hook, app)
|
||||
|
||||
themes(app)
|
||||
|
||||
return app
|
||||
|
||||
|
||||
def setup_mfa_app(test):
|
||||
test.app = test_create_dummy_app()
|
||||
mfa_init_app(test.app)
|
||||
test.tester = test.app.test_client()
|
||||
|
||||
|
||||
class MockUserMFA():
|
||||
"""Mock user for UserMFA"""
|
||||
def __init__(self, user_id, mfa_auth, options):
|
||||
self.user_id = user_id
|
||||
self.mfa_auth = mfa_auth
|
||||
self.options = options
|
||||
|
||||
|
||||
class MockCurrentUserId():
|
||||
id = 1
|
||||
Reference in New Issue
Block a user