1) Added support for setting PostgreSQL connection parameters. #4728

2) Fixed an issue where Kerberos authentication to the server is not imported/exported. #5732
3) Increase the length of the value column of the setting table. #5746
4) Upgrade Flask-Migrate to 4.0.0. #5525
This commit is contained in:
Akshay Joshi
2023-01-23 17:19:59 +05:30
committed by GitHub
parent 91049445dd
commit a7cf698d09
31 changed files with 594 additions and 616 deletions

View File

@@ -254,8 +254,6 @@ class Connection(BaseConnection):
else:
return True, None
pg_conn = None
passfile = None
manager = self.manager
crypt_key_present, crypt_key = get_crypt_key()
@@ -299,7 +297,7 @@ class Connection(BaseConnection):
# we will check for pgpass file availability from connection manager
# if it's present then we will use it
if not password and not encpass and not passfile:
passfile = manager.passfile if manager.passfile else None
passfile = manager.get_connection_param_value('passfile')
if manager.passexec:
password = manager.passexec.get()
@@ -315,8 +313,10 @@ class Connection(BaseConnection):
os.environ['PGAPPNAME'] = '{0} - {1}'.format(
config.APP_NAME, conn_id)
ssl_key = get_complete_file_path(manager.sslkey)
if ssl_key and manager.ssl_mode in \
ssl_key = get_complete_file_path(
manager.get_connection_param_value('sslkey'))
sslmode = manager.get_connection_param_value('sslmode')
if ssl_key and sslmode in \
['require', 'verify-ca', 'verify-full']:
ssl_key_file_permission = \
int(oct(os.stat(ssl_key).st_mode)[-3:])
@@ -324,27 +324,12 @@ class Connection(BaseConnection):
os.chmod(ssl_key, 0o600)
with ConnectionLocker(manager.kerberos_conn):
pg_conn = psycopg2.connect(
host=manager.local_bind_host if manager.use_ssh_tunnel
else manager.host,
hostaddr=manager.local_bind_host if manager.use_ssh_tunnel
else manager.hostaddr,
port=manager.local_bind_port if manager.use_ssh_tunnel
else manager.port,
database=database,
user=user,
password=password,
async_=self.async_,
passfile=get_complete_file_path(passfile),
sslmode=manager.ssl_mode,
sslcert=get_complete_file_path(manager.sslcert),
sslkey=ssl_key,
sslrootcert=get_complete_file_path(manager.sslrootcert),
sslcrl=get_complete_file_path(manager.sslcrl),
sslcompression=True if manager.sslcompression else False,
service=manager.service,
connect_timeout=manager.connect_timeout
)
# Create the connection string
connection_string = manager.create_connection_string(
database, user, password)
pg_conn = psycopg2.connect(connection_string,
async_=self.async_)
# If connection is asynchronous then we will have to wait
# until the connection is ready to use.
@@ -1413,7 +1398,6 @@ WHERE db.datname = current_database()""")
def reset(self):
if self.conn and self.conn.closed:
self.conn = None
pg_conn = None
manager = self.manager
is_return, return_value, password = self._decrypt_password(manager)
@@ -1422,26 +1406,11 @@ WHERE db.datname = current_database()""")
try:
with ConnectionLocker(manager.kerberos_conn):
pg_conn = psycopg2.connect(
host=manager.local_bind_host if manager.use_ssh_tunnel
else manager.host,
hostaddr=manager.local_bind_host if manager.use_ssh_tunnel
else manager.hostaddr,
port=manager.local_bind_port if manager.use_ssh_tunnel
else manager.port,
database=self.db,
user=manager.user,
password=password,
passfile=get_complete_file_path(manager.passfile),
sslmode=manager.ssl_mode,
sslcert=get_complete_file_path(manager.sslcert),
sslkey=get_complete_file_path(manager.sslkey),
sslrootcert=get_complete_file_path(manager.sslrootcert),
sslcrl=get_complete_file_path(manager.sslcrl),
sslcompression=True if manager.sslcompression else False,
service=manager.service,
connect_timeout=manager.connect_timeout
)
# Create the connection string
connection_string = manager.create_connection_string(
self.db, manager.user, password)
pg_conn = psycopg2.connect(connection_string)
except psycopg2.Error as e:
if e.pgerror:
@@ -1725,30 +1694,12 @@ Failed to reset the connection to the server due to following error:
try:
with ConnectionLocker(self.manager.kerberos_conn):
pg_conn = psycopg2.connect(
host=self.manager.local_bind_host if
self.manager.use_ssh_tunnel else self.manager.host,
hostaddr=self.manager.local_bind_host if
self.manager.use_ssh_tunnel else
self.manager.hostaddr,
port=self.manager.local_bind_port if
self.manager.use_ssh_tunnel else self.manager.port,
database=self.db,
user=self.manager.user,
password=password,
passfile=get_complete_file_path(self.manager.passfile),
sslmode=self.manager.ssl_mode,
sslcert=get_complete_file_path(self.manager.sslcert),
sslkey=get_complete_file_path(self.manager.sslkey),
sslrootcert=get_complete_file_path(
self.manager.sslrootcert
),
sslcrl=get_complete_file_path(self.manager.sslcrl),
sslcompression=True if self.manager.sslcompression
else False,
service=self.manager.service,
connect_timeout=self.manager.connect_timeout
)
# Create the connection string
connection_string = \
self.manager.create_connection_string(
self.db, self.manager.user, password)
pg_conn = psycopg2.connect(connection_string)
# Get the cursor and run the query
cur = pg_conn.cursor()
@@ -1756,7 +1707,6 @@ Failed to reset the connection to the server due to following error:
# Close the connection
pg_conn.close()
pg_conn = None
except psycopg2.Error as e:
status = False

View File

@@ -49,6 +49,7 @@ class ServerManager():
self.local_bind_port = None
self.tunnel_object = None
self.tunnel_created = False
self.connection_string = ''
self.update(server)
@@ -65,7 +66,6 @@ class ServerManager():
self.sid = server.id
self.host = server.host
self.hostaddr = server.hostaddr
self.port = server.port
self.db = server.maintenance_db
self.shared = server.shared
@@ -73,23 +73,14 @@ class ServerManager():
self.user = server.username
self.password = server.password
self.role = server.role
self.ssl_mode = server.ssl_mode
self.pinged = datetime.datetime.now()
self.db_info = dict()
self.server_types = None
self.db_res = server.db_res
self.passfile = server.passfile
self.passexec = \
PasswordExec(server.passexec_cmd, server.passexec_expiration) \
if server.passexec_cmd else None
self.sslcert = server.sslcert
self.sslkey = server.sslkey
self.sslrootcert = server.sslrootcert
self.sslcrl = server.sslcrl
self.sslcompression = True if server.sslcompression else False
self.service = server.service
self.connect_timeout = \
server.connect_timeout if server.connect_timeout else 0
if config.SUPPORT_SSH_TUNNEL:
self.use_ssh_tunnel = server.use_ssh_tunnel
self.tunnel_host = server.tunnel_host
@@ -113,6 +104,9 @@ class ServerManager():
self.kerberos_conn = server.kerberos_conn
self.gss_authenticated = False
self.gss_encrypted = False
self.connection_params = server.connection_params
self.connection_string = self.create_connection_string(self.db,
self.user)
for con in self.connections:
self.connections[con]._release()
@@ -623,3 +617,53 @@ WHERE db.oid = {0}""".format(did))
self.local_bind_port = None
self.tunnel_object = None
self.tunnel_created = False
def get_connection_param_value(self, param_name):
"""
This function return the value of param_name if found in the
connection parameter.
"""
value = None
if self.connection_params and param_name in self.connection_params:
value = self.connection_params[param_name]
return value
def create_connection_string(self, database, user, password=None):
"""
This function is used to create connection string based on the
parameters.
"""
full_connection_string = \
'host=\'{0}\' port=\'{1}\' dbname=\'{2}\' user=\'{3}\''.format(
self.local_bind_host if self.use_ssh_tunnel else self.host,
self.local_bind_port if self.use_ssh_tunnel else self.port,
database, user)
# Loop through all the connection parameters set in the server dialog.
if self.connection_params and isinstance(self.connection_params, dict):
for key, value in self.connection_params.items():
# Getting complete file path if the key is one of the below.
if key in ['passfile', 'sslcert', 'sslkey', 'sslrootcert',
'sslcrl', 'service', 'sslcrldir']:
value = get_complete_file_path(value)
# In case of host address need to check ssh tunnel flag.
if key == 'hostaddr':
value = self.local_bind_host if self.use_ssh_tunnel else \
value
full_connection_string = \
"{0} {1}='{2}'".format(full_connection_string, key, value)
# Password should not be visible into the connection string, so
# setting the class variable with password to 'xxxxxxx'.
if password:
self.connection_string = "{0} password='xxxxxxx'".format(
full_connection_string)
if password:
full_connection_string = "{0} password='{1}'".format(
full_connection_string, password)
return full_connection_string