Fixed following issues: (#6361)

1) Ensure that SSH Tunnel should work properly after upgrading to 7.2 from 7.1. #6341
2) Ensure that the master password dialog should not visible if the parameter MASTER_PASSWORD_REQUIRED is set to False. #6353
This commit is contained in:
Nikhil Mohite 2023-06-05 12:45:34 +05:30 committed by GitHub
parent 10077f13c4
commit f6275688e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 112 additions and 47 deletions

View File

@ -18,7 +18,7 @@ from smtplib import SMTPConnectError, SMTPResponseException, \
from socket import error as SOCKETErrorException
from urllib.request import urlopen
from pgadmin.utils.constants import KEY_RING_SERVICE_NAME, \
KEY_RING_USERNAME_FORMAT, KEY_RING_DESKTOP_USER
KEY_RING_USERNAME_FORMAT, KEY_RING_DESKTOP_USER, KEY_RING_TUNNEL_FORMAT
import time
@ -60,6 +60,7 @@ from pgadmin.utils.constants import MIMETYPE_APP_JS, PGADMIN_NODE,\
INTERNAL, KERBEROS, LDAP, QT_DEFAULT_PLACEHOLDER, OAUTH2, WEBSERVER,\
VW_EDT_DEFAULT_PLACEHOLDER
from pgadmin.authenticate import AuthSourceManager
from pgadmin.utils.exception import CryptKeyMissing
try:
from flask_security.views import default_render_json
@ -823,8 +824,9 @@ def set_master_password():
if data != '':
data = json.loads(data)
if not config.DISABLED_LOCAL_PASSWORD_STORAGE:
if data.get('password') and \
if not config.DISABLED_LOCAL_PASSWORD_STORAGE and \
(config.ALLOW_SAVE_PASSWORD or config.ALLOW_SAVE_TUNNEL_PASSWORD):
if data.get('password') and config.MASTER_PASSWORD_REQUIRED and\
not validate_master_password(data.get('password')):
return form_master_password_response(
present=False,
@ -834,6 +836,13 @@ def set_master_password():
from pgadmin.model import Server
from pgadmin.utils.crypto import decrypt
desktop_user = current_user
enc_key = data['password']
if not config.MASTER_PASSWORD_REQUIRED:
status, enc_key = get_crypt_key()
if not status:
raise CryptKeyMissing
try:
all_server = Server.query.all()
# pgAdmin will use the OS password manager to store the server
@ -841,20 +850,34 @@ def set_master_password():
# OS password manager
if keyring.get_password(
KEY_RING_SERVICE_NAME, KEY_RING_DESKTOP_USER.format(
desktop_user.username)) or data['password']:
desktop_user.username)) or enc_key:
is_migrated = False
for server in all_server:
if server.password and data['password'] \
and server.save_password:
name = KEY_RING_USERNAME_FORMAT.format(server.name,
server.id)
password = decrypt(server.password,
data['password']).decode()
# Store the password using OS password manager
keyring.set_password(KEY_RING_SERVICE_NAME, name,
password)
is_migrated = True
setattr(server, 'password', None)
if enc_key:
if server.password and config.ALLOW_SAVE_PASSWORD \
and server.save_password:
name = KEY_RING_USERNAME_FORMAT.format(server.name,
server.id)
password = decrypt(server.password,
enc_key).decode()
# Store the password using OS password manager
keyring.set_password(KEY_RING_SERVICE_NAME, name,
password)
is_migrated = True
setattr(server, 'password', None)
if server.tunnel_password and \
config.ALLOW_SAVE_TUNNEL_PASSWORD:
tname = KEY_RING_TUNNEL_FORMAT.format(server.name,
server.id)
tpassword = decrypt(server.tunnel_password,
enc_key).decode()
# Store the password using OS password manager
keyring.set_password(KEY_RING_SERVICE_NAME, tname,
tpassword)
is_migrated = True
setattr(server, 'tunnel_password', None)
db.session.commit()
@ -869,6 +892,10 @@ def set_master_password():
)
else:
if len(all_server) == 0:
# Store the password using OS password manager
keyring.set_password(KEY_RING_SERVICE_NAME,
KEY_RING_DESKTOP_USER.format(
desktop_user.username), 'test')
return form_master_password_response(
present=True,
)
@ -876,11 +903,20 @@ def set_master_password():
is_master_password_present = True
keyring_name = ''
for server in all_server:
if server.password and server.save_password:
is_password_present = \
server.save_password or server.tunnel_password
if server.password and is_password_present:
is_master_password_present = False
keyring_name = config.KEYRING_NAME
break
if is_master_password_present:
# Store the password using OS password manager
keyring.set_password(KEY_RING_SERVICE_NAME,
KEY_RING_DESKTOP_USER.format(
desktop_user.username),
'test')
return form_master_password_response(
present=is_master_password_present,
keyring_name=keyring_name

View File

@ -34,7 +34,7 @@ from pgadmin.utils.constants import UNAUTH_REQ, MIMETYPE_APP_JS, \
from sqlalchemy import or_
from pgadmin.utils.preferences import Preferences
from pgadmin.utils.constants import KEY_RING_SERVICE_NAME, \
KEY_RING_USERNAME_FORMAT, KEY_RING_TUNNEL_FORMAT
KEY_RING_USERNAME_FORMAT, KEY_RING_TUNNEL_FORMAT, KEY_RING_DESKTOP_USER
from .... import socketio as sio
import keyring
@ -249,6 +249,21 @@ class ServerModule(sg.ServerGroupPluginModule):
current_app.logger.exception(e)
errmsg = str(e)
is_password_saved = bool(server.save_password)
is_tunnel_password_saved = bool(server.tunnel_password)
if not config.DISABLED_LOCAL_PASSWORD_STORAGE:
sname = KEY_RING_USERNAME_FORMAT.format(server.name, server.id)
spassword = keyring.get_password(
KEY_RING_SERVICE_NAME, sname)
is_password_saved = bool(spassword)
tunnelname = KEY_RING_TUNNEL_FORMAT.format(server.name,
server.id)
tunnel_password = keyring.get_password(KEY_RING_SERVICE_NAME,
tunnelname)
is_tunnel_password_saved = bool(tunnel_password)
yield self.generate_browser_node(
"%d" % (server.id),
gid,
@ -265,9 +280,8 @@ class ServerModule(sg.ServerGroupPluginModule):
wal_pause=wal_paused,
host=server.host,
port=server.port,
is_password_saved=bool(server.save_password),
is_tunnel_password_saved=True
if server.tunnel_password is not None else False,
is_password_saved=is_password_saved,
is_tunnel_password_saved=is_tunnel_password_saved,
was_connected=was_connected,
errmsg=errmsg,
user_id=server.user_id,
@ -577,6 +591,22 @@ class ServerNode(PGChildNodeView):
manager.release()
errmsg = "{0} : {1}".format(server.name, result)
is_password_saved = bool(server.save_password)
is_tunnel_password_saved = bool(server.tunnel_password)
if not config.DISABLED_LOCAL_PASSWORD_STORAGE:
sname = KEY_RING_USERNAME_FORMAT.format(server.name, server.id)
spassword = keyring.get_password(
KEY_RING_SERVICE_NAME, sname)
is_password_saved = bool(spassword)
tunnelname = KEY_RING_TUNNEL_FORMAT.format(server.name,
server.id)
tunnel_password = keyring.get_password(KEY_RING_SERVICE_NAME,
tunnelname)
is_tunnel_password_saved = bool(tunnel_password)
res.append(
self.blueprint.generate_browser_node(
"%d" % (server.id),
@ -593,9 +623,8 @@ class ServerNode(PGChildNodeView):
user=manager.user_info if connected else None,
in_recovery=in_recovery,
wal_pause=wal_paused,
is_password_saved=bool(server.save_password),
is_tunnel_password_saved=True
if server.tunnel_password is not None else False,
is_password_saved=is_password_saved,
is_tunnel_password_saved=is_tunnel_password_saved,
errmsg=errmsg,
username=server.username,
shared=server.shared,
@ -720,16 +749,16 @@ class ServerNode(PGChildNodeView):
db.session.delete(s)
if not config.DISABLED_LOCAL_PASSWORD_STORAGE:
try:
server_name = KEY_RING_USERNAME_FORMAT.format(
sname = KEY_RING_USERNAME_FORMAT.format(
s.name,
s.id)
# Get password form OS password manager
is_present = keyring.get_password(
KEY_RING_SERVICE_NAME, server_name)
KEY_RING_SERVICE_NAME, sname)
# Delete saved password from OS password manager
if is_present:
keyring.delete_password(KEY_RING_SERVICE_NAME,
server_name)
sname)
except keyring.errors.KeyringError as e:
config.DISABLED_LOCAL_PASSWORD_STORAGE = True
db.session.commit()
@ -1442,7 +1471,10 @@ class ServerNode(PGChildNodeView):
conn = manager.connection()
crypt_key = None
if config.DISABLED_LOCAL_PASSWORD_STORAGE:
if config.DISABLED_LOCAL_PASSWORD_STORAGE or \
not keyring.get_password(KEY_RING_SERVICE_NAME,
KEY_RING_DESKTOP_USER.format(
current_user.username)):
# Get enc key
crypt_key_present, crypt_key = get_crypt_key()
if not crypt_key_present:
@ -1462,6 +1494,7 @@ class ServerNode(PGChildNodeView):
KEY_RING_SERVICE_NAME,
KEY_RING_TUNNEL_FORMAT.format(server.name,
server.id))
prompt_tunnel_password = bool(tunnel_password)
else:
tunnel_password = server.tunnel_password
else:
@ -1477,12 +1510,7 @@ class ServerNode(PGChildNodeView):
tunnel_password = encrypt(tunnel_password, crypt_key) \
if tunnel_password is not None else \
server.tunnel_password
else:
# Get password form OS password manager
tunnel_password = keyring.get_password(
KEY_RING_SERVICE_NAME,
KEY_RING_TUNNEL_FORMAT.format(server.name,
server.id))
except Exception as e:
current_app.logger.exception(e)
return internal_server_error(errormsg=str(e))
@ -1525,7 +1553,7 @@ class ServerNode(PGChildNodeView):
except Exception as e:
current_app.logger.exception(e)
return internal_server_error(errormsg=str(e))
elif save_password:
elif save_password and config.ALLOW_SAVE_PASSWORD:
# Store the password using OS password manager
keyring.set_password(
KEY_RING_SERVICE_NAME,
@ -1584,7 +1612,7 @@ class ServerNode(PGChildNodeView):
# Save the encrypted password using the user's login
# password key, if there is any password to save
if password and config.SERVER_MODE:
if password and config.DISABLED_LOCAL_PASSWORD_STORAGE:
if server.shared and server.user_id != current_user.id:
setattr(shared_server, 'password', password)
else:
@ -1600,8 +1628,18 @@ class ServerNode(PGChildNodeView):
if save_tunnel_password and config.ALLOW_SAVE_TUNNEL_PASSWORD:
try:
# Save the encrypted tunnel password.
setattr(server, 'tunnel_password', tunnel_password)
if config.DISABLED_LOCAL_PASSWORD_STORAGE:
# Save the encrypted tunnel password.
setattr(server, 'tunnel_password', tunnel_password)
else:
# Store the password using OS password manager
keyring.set_password(
KEY_RING_SERVICE_NAME,
KEY_RING_TUNNEL_FORMAT.format(server.name,
server.id),
tunnel_password)
setattr(server, 'tunnel_password', None)
db.session.commit()
except Exception as e:
# Release Connection

View File

@ -202,15 +202,12 @@ export function showMasterPassword(isPWDPresent, errmsg, masterpass_callback_que
const api = getApiInstance();
let title = keyring_name.length > 0 ? gettext('Migrate Saved Passwords') : isPWDPresent ? gettext('Unlock Saved Passwords') : gettext('Set Master Password');
mountDialog(title, (onClose, setNewSize)=> {
Notify.showModal(title, (onClose)=> {
return <Theme>
<MasterPasswordContent
isPWDPresent= {isPWDPresent}
data={{'errmsg': errmsg}}
keyringName={keyring_name}
setHeight={(containerHeight) => {
setNewSize(pgAdmin.Browser.stdW.md, containerHeight);
}}
closeModal={() => {
onClose();
}}

View File

@ -571,12 +571,6 @@ WHERE db.oid = {0}""".format(did))
# password is in bytes, for python3 we need it in string
if isinstance(tunnel_password, bytes):
tunnel_password = tunnel_password.decode()
else:
# Get password form OS password manager
tunnel_password = keyring.get_password(
KEY_RING_SERVICE_NAME,
KEY_RING_TUNNEL_FORMAT.format(self.manager.name,
self.manager.sid))
except Exception as e:
current_app.logger.exception(e)