Revert "1) Added support for Kerberos authentication, using SPNEGO to forward the Kerberos tickets through a browser. Fixes #5457"

This reverts commit 6ead597b43.
This commit is contained in:
Akshay Joshi
2021-01-14 14:46:59 +05:30
parent 6ead597b43
commit f0debdd513
22 changed files with 40 additions and 474 deletions

View File

@@ -29,7 +29,7 @@ from flask_security.recoverable import reset_password_token_status, \
generate_reset_password_token, update_password
from flask_security.signals import reset_password_instructions_sent
from flask_security.utils import config_value, do_flash, get_url, \
get_message, slash_url_suffix, login_user, send_mail, logout_user
get_message, slash_url_suffix, login_user, send_mail
from flask_security.views import _security, _commit, _ctx
from werkzeug.datastructures import MultiDict
@@ -47,8 +47,7 @@ from pgadmin.utils.master_password import validate_master_password, \
set_masterpass_check_text, cleanup_master_password, get_crypt_key, \
set_crypt_key, process_masterpass_disabled
from pgadmin.model import User
from pgadmin.utils.constants import MIMETYPE_APP_JS, PGADMIN_NODE,\
INTERNAL, KERBEROS
from pgadmin.utils.constants import MIMETYPE_APP_JS, PGADMIN_NODE
try:
from flask_security.views import default_render_json
@@ -281,8 +280,7 @@ class BrowserModule(PgAdminModule):
'browser.check_master_password',
'browser.set_master_password',
'browser.reset_master_password',
'browser.lock_layout'
]
'browser.lock_layout']
blueprint = BrowserModule(MODULE_NAME, __name__)
@@ -541,12 +539,6 @@ class BrowserPluginModule(PgAdminModule):
def _get_logout_url():
if config.SERVER_MODE and\
session['_auth_source_manager_obj']['current_source'] == \
KERBEROS:
return '{0}?next={1}'.format(url_for(
'authenticate.kerberos_logout'), url_for(BROWSER_INDEX))
return '{0}?next={1}'.format(
url_for('security.logout'), url_for(BROWSER_INDEX))
@@ -672,18 +664,13 @@ def index():
auth_only_internal = False
auth_source = []
session['allow_save_password'] = True
if config.SERVER_MODE:
if len(config.AUTHENTICATION_SOURCES) == 1\
and INTERNAL in config.AUTHENTICATION_SOURCES:
and 'internal' in config.AUTHENTICATION_SOURCES:
auth_only_internal = True
auth_source = session['_auth_source_manager_obj'][
'source_friendly_name']
if session['_auth_source_manager_obj']['current_source'] == KERBEROS:
session['allow_save_password'] = False
response = Response(render_template(
MODULE_NAME + "/index.html",
username=current_user.username,
@@ -1099,7 +1086,7 @@ if hasattr(config, 'SECURITY_RECOVERABLE') and config.SECURITY_RECOVERABLE:
# Check the Authentication source of the User
user = User.query.filter_by(
email=form.data['email'],
auth_source=INTERNAL
auth_source=current_app.PGADMIN_DEFAULT_AUTH_SOURCE
).first()
if user is None:

View File

@@ -10,7 +10,7 @@
import simplejson as json
import pgadmin.browser.server_groups as sg
from flask import render_template, request, make_response, jsonify, \
current_app, url_for, session
current_app, url_for
from flask_babelex import gettext
from flask_security import current_user, login_required
from pgadmin.browser.server_groups.servers.types import ServerType
@@ -1822,13 +1822,7 @@ class ServerNode(PGChildNodeView):
_=gettext,
service=server.service,
prompt_tunnel_password=prompt_tunnel_password,
prompt_password=prompt_password,
allow_save_password=True if
config.ALLOW_SAVE_PASSWORD and
session['allow_save_password'] else False,
allow_save_tunnel_password=True if
config.ALLOW_SAVE_TUNNEL_PASSWORD and
session['allow_save_password'] else False
prompt_password=prompt_password
)
)
else:
@@ -1842,9 +1836,6 @@ class ServerNode(PGChildNodeView):
errmsg=errmsg,
service=server.service,
_=gettext,
allow_save_password=True if
config.ALLOW_SAVE_PASSWORD and
session['allow_save_password'] else False,
)
)

View File

@@ -19,7 +19,7 @@
<div class="col-sm-10">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" id="save_password" name="save_password" type="checkbox"
{% if not allow_save_password %}disabled{% endif %}
{% if not config.ALLOW_SAVE_PASSWORD %}disabled{% endif %}
>
<label class="custom-control-label" for="save_password">{{ _('Save Password') }}</label>
</div>

View File

@@ -15,7 +15,7 @@
<div class="w-100">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" id="save_tunnel_password" name="save_tunnel_password" type="checkbox"
{% if not allow_save_tunnel_password %}disabled{% endif %}
{% if not config.ALLOW_SAVE_TUNNEL_PASSWORD %}disabled{% endif %}
>
<label class="custom-control-label" for="save_tunnel_password" class="ml-1">{{ _('Save Password') }}</label>
</div>
@@ -39,7 +39,7 @@
<div class="w-100">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" id="save_password" name="save_password" type="checkbox"
{% if not allow_save_password %}disabled{% endif %}
{% if not config.ALLOW_SAVE_PASSWORD %}disabled{% endif %}
>
<label class="custom-control-label" for="save_password" class="ml-1">{{ _('Save Password') }}</label>
</div>

View File

@@ -1,16 +0,0 @@
{% extends "base.html" %}
{% block body %}
<div class="container-fluid change_pass">
<div class="row align-items-center h-100">
<div class="col-md-5"></div>
<div class="col-md-5">
<div class="panel-header h4"><i class="app-icon pg-icon-blue" aria-hidden="true"></i> {{ _('%(appname)s', appname=config.APP_NAME) }}</div>
<div class="panel-body">
<div class="d-block text-color pb-3 h5">{{ _('Login Failed.') }}</div>
<div><a href="{{ login_url }}">Click here</a> to Login again.</div>
</div>
</div>
<div class="col-md-4"></div>
</div>
</div>
{% endblock %}

View File

@@ -1,16 +0,0 @@
{% extends "base.html" %}
{% block body %}
<div class="container-fluid change_pass">
<div class="row align-items-center h-100">
<div class="col-md-5"></div>
<div class="col-md-5">
<div class="panel-header h4"><i class="app-icon pg-icon-blue" aria-hidden="true"></i> {{ _('%(appname)s', appname=config.APP_NAME) }}</div>
<div class="panel-body">
<div class="d-block text-color pb-3 h5">{{ _('Logged out successfully.') }}</div>
<div><a href="{{ login_url }}">Click here</a> to Login again.</div>
</div>
</div>
<div class="col-md-4"></div>
</div>
</div>
{% endblock %}

View File

@@ -1,104 +0,0 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2021, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################
import config as app_config
from pgadmin.utils.route import BaseTestGenerator
from regression.python_test_utils import test_utils as utils
from pgadmin.authenticate.registry import AuthSourceRegistry
from unittest.mock import patch, MagicMock
class KerberosLoginMockTestCase(BaseTestGenerator):
"""
This class checks Spnego/Kerberos login functionality by mocking
HTTP negotiate authentication.
"""
scenarios = [
('Spnego/Kerberos Authentication: Test Unauthorized', dict(
auth_source=['kerberos'],
auto_create_user=True,
flag=1
)),
('Spnego/Kerberos Authentication: Test Authorized', dict(
auth_source=['kerberos'],
auto_create_user=True,
flag=2
))
]
@classmethod
def setUpClass(cls):
"""
We need to logout the test client as we are testing
spnego/kerberos login scenarios.
"""
cls.tester.logout()
def setUp(self):
app_config.AUTHENTICATION_SOURCES = self.auth_source
self.app.PGADMIN_EXTERNAL_AUTH_SOURCE = 'kerberos'
def runTest(self):
"""This function checks spnego/kerberos login functionality."""
if self.flag == 1:
self.test_unauthorized()
elif self.flag == 2:
if app_config.SERVER_MODE is False:
self.skipTest(
"Can not run Kerberos Authentication in the Desktop mode."
)
self.test_authorized()
def test_unauthorized(self):
"""
Ensure that when client sends the first request,
the Negotiate request is sent.
"""
res = self.tester.login(None, None, True)
self.assertEqual(res.status_code, 401)
self.assertEqual(res.headers.get('www-authenticate'), 'Negotiate')
def test_authorized(self):
"""
Ensure that when the client sends an correct authorization token,
they receive a 200 OK response and the user principal is extracted and
passed on to the routed method.
"""
class delCrads:
def __init__(self):
self.initiator_name = 'user@PGADMIN.ORG'
del_crads = delCrads()
AuthSourceRegistry.registry['kerberos'].negotiate_start = MagicMock(
return_value=[True, del_crads])
res = self.tester.login(None,
None,
True,
headers={'Authorization': 'Negotiate CTOKEN'}
)
self.assertEqual(res.status_code, 200)
respdata = 'Gravatar image for %s' % del_crads.initiator_name
self.assertTrue(respdata in res.data.decode('utf8'))
def tearDown(self):
self.app.PGADMIN_EXTERNAL_AUTH_SOURCE = 'ldap'
self.tester.logout()
@classmethod
def tearDownClass(cls):
"""
We need to again login the test client as soon as test scenarios
finishes.
"""
cls.tester.logout()
app_config.AUTHENTICATION_SOURCES = ['internal']
utils.login_tester_account(cls.tester)