Allow pgAdmin to retrieve master password from external script/program. #4769

This commit is contained in:
Yogesh Mahajan
2023-05-25 13:49:08 +05:30
committed by GitHub
parent cba3dc9457
commit 702bc8c8ce
5 changed files with 126 additions and 13 deletions

View File

@@ -11,7 +11,7 @@ import json
import logging
import os
import sys
from abc import ABCMeta, abstractmethod, abstractproperty
from abc import ABCMeta, abstractmethod
from smtplib import SMTPConnectError, SMTPResponseException, \
SMTPServerDisconnected, SMTPDataError, SMTPHeloError, SMTPException, \
SMTPAuthenticationError, SMTPSenderRefused, SMTPRecipientsRefused
@@ -35,7 +35,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, \
get_post_logout_redirect
from flask_security.views import _security, view_commit, _ctx
from werkzeug.datastructures import MultiDict
@@ -793,7 +793,12 @@ def reset_master_password():
KEY_RING_DESKTOP_USER.format(
current_user.username), 'test')
cleanup_master_password()
return make_json_response(data=get_crypt_key()[0])
status, crypt_key = get_crypt_key()
# Set masterpass_check if MASTER_PASSWORD_HOOK is set which provides
# encryption key
if config.MASTER_PASSWORD_REQUIRED and config.MASTER_PASSWORD_HOOK:
set_masterpass_check_text(crypt_key)
return make_json_response(data=status)
@blueprint.route("/master_password", endpoint="set_master_password",
@@ -872,9 +877,28 @@ def set_master_password():
)
config.DISABLED_LOCAL_PASSWORD_STORAGE = True
# Master password is not applicable for server mode
# Enable master password if oauth is used
if not config.SERVER_MODE or OAUTH2 in config.AUTHENTICATION_SOURCES \
# If the master password is required and the master password hook
# is specified then try to retrieve the encryption key and update data.
# If there is an error while retrieving it, return an error message.
if config.SERVER_MODE and config.MASTER_PASSWORD_REQUIRED and \
config.MASTER_PASSWORD_HOOK:
status, enc_key = get_crypt_key()
if status:
data = {'password': enc_key, 'submit_password': True}
else:
error = gettext('The master password could not be retrieved from '
'the MASTER_PASSWORD_HOOK utility specified {0}.'
'Please check that the hook utility is configured'
' correctly.'.format(config.MASTER_PASSWORD_HOOK))
return form_master_password_response(
existing=False,
present=False,
errmsg=error
)
# Master password is applicable for Desktop mode and in server mode
# only when auth sources are oauth, kerberos, webserver.
if (not config.SERVER_MODE) or OAUTH2 in config.AUTHENTICATION_SOURCES \
or KERBEROS in config.AUTHENTICATION_SOURCES \
or WEBSERVER in config.AUTHENTICATION_SOURCES \
and config.MASTER_PASSWORD_REQUIRED:
@@ -882,12 +906,16 @@ def set_master_password():
if current_user.masterpass_check is not None and \
data.get('submit_password', False) and \
not validate_master_password(data.get('password')):
errmsg = gettext("Password mismatch error") if \
config.MASTER_PASSWORD_HOOK else \
gettext("Incorrect master password")
return form_master_password_response(
existing=True,
present=False,
errmsg=gettext("Incorrect master password")
errmsg=errmsg
)
# if master password received in request
if data != '' and data.get('password', '') != '':
# store the master pass in the memory
@@ -908,16 +936,23 @@ def set_master_password():
# master pass
set_masterpass_check_text(data.get('password'))
# If password in request is empty then try to get it with
# get_crypt_key method. If get_crypt_key() returns false status and
# masterpass_check is already set, provide a pop to enter
# master password(present) without the reset option.(existing).
elif not get_crypt_key()[0] and \
current_user.masterpass_check is not None:
return form_master_password_response(
existing=True,
present=False,
)
# If get_crypt_key return True,but crypt_key is none and
# user entered blank password, return error message.
elif not get_crypt_key()[1]:
error_message = None
# If user attempted to enter a blank password, then throw error
if data.get('submit_password') and data.get('password') == '':
# If user attempted to enter a blank password, then throw error
error_message = gettext("Master password cannot be empty")
return form_master_password_response(
existing=False,