mirror of
https://github.com/pgadmin-org/pgadmin4.git
synced 2025-02-25 18:55:31 -06:00
Added encrypted password in reverse engineered SQL for roles. Fixes #1974.
This commit is contained in:
parent
5b438e13cc
commit
02642628b0
@ -9,6 +9,7 @@ This release contains a number of bug fixes and new features since the release o
|
|||||||
New features
|
New features
|
||||||
************
|
************
|
||||||
|
|
||||||
|
| `Issue #1974 <https://redmine.postgresql.org/issues/1974>`_ - Added encrypted password in reverse engineered SQL for roles.
|
||||||
|
|
||||||
Housekeeping
|
Housekeeping
|
||||||
************
|
************
|
||||||
|
@ -735,9 +735,10 @@ rolmembership:{
|
|||||||
|
|
||||||
@check_precondition()
|
@check_precondition()
|
||||||
def sql(self, gid, sid, rid):
|
def sql(self, gid, sid, rid):
|
||||||
|
show_password = self.conn.manager.user_info['is_superuser']
|
||||||
status, res = self.conn.execute_scalar(
|
status, res = self.conn.execute_scalar(
|
||||||
render_template(
|
render_template(
|
||||||
self.sql_path + 'sql.sql'
|
self.sql_path + 'sql.sql', show_password=show_password
|
||||||
),
|
),
|
||||||
dict({'rid': rid})
|
dict({'rid': rid})
|
||||||
)
|
)
|
||||||
|
@ -8,7 +8,6 @@ FROM
|
|||||||
pg_catalog.quote_ident(rolname) || E';\n\nCREATE ROLE ' ||
|
pg_catalog.quote_ident(rolname) || E';\n\nCREATE ROLE ' ||
|
||||||
pg_catalog.quote_ident(rolname) || E' WITH\n ' ||
|
pg_catalog.quote_ident(rolname) || E' WITH\n ' ||
|
||||||
CASE WHEN rolcanlogin THEN 'LOGIN' ELSE 'NOLOGIN' END || E'\n ' ||
|
CASE WHEN rolcanlogin THEN 'LOGIN' ELSE 'NOLOGIN' END || E'\n ' ||
|
||||||
CASE WHEN rolcanlogin AND rolpassword LIKE 'md5%%' THEN 'ENCRYPTED PASSWORD ' || quote_literal(rolpassword) || E'\n ' ELSE '' END ||
|
|
||||||
CASE WHEN rolsuper THEN 'SUPERUSER' ELSE 'NOSUPERUSER' END || E'\n ' ||
|
CASE WHEN rolsuper THEN 'SUPERUSER' ELSE 'NOSUPERUSER' END || E'\n ' ||
|
||||||
CASE WHEN rolinherit THEN 'INHERIT' ELSE 'NOINHERIT' END || E'\n ' ||
|
CASE WHEN rolinherit THEN 'INHERIT' ELSE 'NOINHERIT' END || E'\n ' ||
|
||||||
CASE WHEN rolcreatedb THEN 'CREATEDB' ELSE 'NOCREATEDB' END || E'\n ' ||
|
CASE WHEN rolcreatedb THEN 'CREATEDB' ELSE 'NOCREATEDB' END || E'\n ' ||
|
||||||
@ -16,6 +15,12 @@ FROM
|
|||||||
-- PostgreSQL >= 9.1
|
-- PostgreSQL >= 9.1
|
||||||
CASE WHEN rolreplication THEN 'REPLICATION' ELSE 'NOREPLICATION' END ||
|
CASE WHEN rolreplication THEN 'REPLICATION' ELSE 'NOREPLICATION' END ||
|
||||||
CASE WHEN rolconnlimit > 0 THEN E'\n CONNECTION LIMIT ' || rolconnlimit ELSE '' END ||
|
CASE WHEN rolconnlimit > 0 THEN E'\n CONNECTION LIMIT ' || rolconnlimit ELSE '' END ||
|
||||||
|
{% if show_password %}
|
||||||
|
(SELECT CASE
|
||||||
|
WHEN (rolpassword LIKE 'md5%%' or rolpassword LIKE 'SCRAM%%') THEN E'\n ENCRYPTED PASSWORD ''' || rolpassword || ''''
|
||||||
|
WHEN rolpassword IS NOT NULL THEN E'\n PASSWORD ''' || rolpassword || ''''
|
||||||
|
ELSE '' END FROM pg_authid au WHERE au.oid=r.oid) ||
|
||||||
|
{% endif %}
|
||||||
CASE WHEN rolvaliduntil IS NOT NULL THEN E'\n VALID UNTIL ' || quote_literal(rolvaliduntil::text) ELSE '' END || ';' AS sql
|
CASE WHEN rolvaliduntil IS NOT NULL THEN E'\n VALID UNTIL ' || quote_literal(rolvaliduntil::text) ELSE '' END || ';' AS sql
|
||||||
FROM
|
FROM
|
||||||
pg_roles r
|
pg_roles r
|
||||||
|
@ -9,6 +9,7 @@ CREATE ROLE "Role2_$%{}[]()&*^!@""'`\/#" WITH
|
|||||||
CREATEROLE
|
CREATEROLE
|
||||||
NOREPLICATION
|
NOREPLICATION
|
||||||
CONNECTION LIMIT 100
|
CONNECTION LIMIT 100
|
||||||
|
ENCRYPTED PASSWORD '<PASSWORD>'
|
||||||
VALID UNTIL '<TIMESTAMPTZ>';
|
VALID UNTIL '<TIMESTAMPTZ>';
|
||||||
|
|
||||||
ALTER ROLE "Role2_$%{}[]()&*^!@""'`\/#" IN DATABASE postgres SET application_name TO 'pg4';
|
ALTER ROLE "Role2_$%{}[]()&*^!@""'`\/#" IN DATABASE postgres SET application_name TO 'pg4';
|
||||||
|
@ -9,6 +9,7 @@ CREATE ROLE "Role2_$%{}[]()&*^!@""'`\/#" WITH
|
|||||||
NOCREATEROLE
|
NOCREATEROLE
|
||||||
NOREPLICATION
|
NOREPLICATION
|
||||||
CONNECTION LIMIT 100
|
CONNECTION LIMIT 100
|
||||||
|
ENCRYPTED PASSWORD '<PASSWORD>'
|
||||||
VALID UNTIL '<TIMESTAMPTZ>';
|
VALID UNTIL '<TIMESTAMPTZ>';
|
||||||
|
|
||||||
ALTER ROLE "Role2_$%{}[]()&*^!@""'`\/#" IN DATABASE postgres SET application_name TO 'pg4';
|
ALTER ROLE "Role2_$%{}[]()&*^!@""'`\/#" IN DATABASE postgres SET application_name TO 'pg4';
|
||||||
|
@ -65,7 +65,8 @@
|
|||||||
},
|
},
|
||||||
"expected_sql_file": "alter_role_options.sql",
|
"expected_sql_file": "alter_role_options.sql",
|
||||||
"expected_msql_file": "alter_role_options.msql",
|
"expected_msql_file": "alter_role_options.msql",
|
||||||
"convert_timestamp_columns": ["rolvaliduntil"]
|
"convert_timestamp_columns": ["rolvaliduntil"],
|
||||||
|
"replace_password": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "delete",
|
"type": "delete",
|
||||||
@ -138,7 +139,8 @@
|
|||||||
},
|
},
|
||||||
"expected_sql_file": "alter_login_role_options.sql",
|
"expected_sql_file": "alter_login_role_options.sql",
|
||||||
"expected_msql_file": "alter_login_role_options.msql",
|
"expected_msql_file": "alter_login_role_options.msql",
|
||||||
"convert_timestamp_columns": ["rolvaliduntil"]
|
"convert_timestamp_columns": ["rolvaliduntil"],
|
||||||
|
"replace_password": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"type": "delete",
|
"type": "delete",
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
|
import re
|
||||||
import traceback
|
import traceback
|
||||||
from flask import url_for
|
from flask import url_for
|
||||||
import regression
|
import regression
|
||||||
@ -103,7 +104,8 @@ class ReverseEngineeredSQLTestCases(BaseTestGenerator):
|
|||||||
# while running the test cases
|
# while running the test cases
|
||||||
self.JSON_PLACEHOLDERS = {'schema_id': '<SCHEMA_ID>',
|
self.JSON_PLACEHOLDERS = {'schema_id': '<SCHEMA_ID>',
|
||||||
'owner': '<OWNER>',
|
'owner': '<OWNER>',
|
||||||
'timestamptz': '<TIMESTAMPTZ>'}
|
'timestamptz': '<TIMESTAMPTZ>',
|
||||||
|
'password': '<PASSWORD>'}
|
||||||
|
|
||||||
resql_module_list = create_resql_module_list(
|
resql_module_list = create_resql_module_list(
|
||||||
BaseTestGenerator.re_sql_module_list,
|
BaseTestGenerator.re_sql_module_list,
|
||||||
@ -416,14 +418,7 @@ class ReverseEngineeredSQLTestCases(BaseTestGenerator):
|
|||||||
fp = open(output_file, "r")
|
fp = open(output_file, "r")
|
||||||
# Used rstrip to remove trailing \n
|
# Used rstrip to remove trailing \n
|
||||||
sql = fp.read().rstrip()
|
sql = fp.read().rstrip()
|
||||||
# Replace place holder <owner> with the current username
|
sql = self.preprocess_expected_sql(scenario, sql, resp_sql)
|
||||||
# used to connect to the database
|
|
||||||
if 'username' in self.server:
|
|
||||||
sql = sql.replace(self.JSON_PLACEHOLDERS['owner'],
|
|
||||||
self.server['username'])
|
|
||||||
# Convert timestamp with timezone from json file to the
|
|
||||||
# database server's correct timestamp
|
|
||||||
sql = self.convert_timestamptz(scenario, sql)
|
|
||||||
try:
|
try:
|
||||||
self.assertEquals(sql, resp_sql)
|
self.assertEquals(sql, resp_sql)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -477,14 +472,7 @@ class ReverseEngineeredSQLTestCases(BaseTestGenerator):
|
|||||||
fp = open(output_file, "r")
|
fp = open(output_file, "r")
|
||||||
# Used rstrip to remove trailing \n
|
# Used rstrip to remove trailing \n
|
||||||
sql = fp.read().rstrip()
|
sql = fp.read().rstrip()
|
||||||
# Replace place holder <owner> with the current username
|
sql = self.preprocess_expected_sql(scenario, sql, resp_sql)
|
||||||
# used to connect to the database
|
|
||||||
if 'username' in self.server:
|
|
||||||
sql = sql.replace(self.JSON_PLACEHOLDERS['owner'],
|
|
||||||
self.server['username'])
|
|
||||||
# Convert timestamp with timezone from json file to the
|
|
||||||
# database server's correct timestamp
|
|
||||||
sql = self.convert_timestamptz(scenario, sql)
|
|
||||||
try:
|
try:
|
||||||
self.assertEquals(sql, resp_sql)
|
self.assertEquals(sql, resp_sql)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -500,14 +488,7 @@ class ReverseEngineeredSQLTestCases(BaseTestGenerator):
|
|||||||
return False
|
return False
|
||||||
elif 'expected_sql' in scenario:
|
elif 'expected_sql' in scenario:
|
||||||
exp_sql = scenario['expected_sql']
|
exp_sql = scenario['expected_sql']
|
||||||
# Replace place holder <owner> with the current username
|
exp_sql = self.preprocess_expected_sql(scenario, exp_sql, resp_sql)
|
||||||
# used to connect to the database
|
|
||||||
if 'username' in self.server:
|
|
||||||
exp_sql = exp_sql.replace(self.JSON_PLACEHOLDERS['owner'],
|
|
||||||
self.server['username'])
|
|
||||||
# Convert timestamp with timezone from json file to the
|
|
||||||
# database server's correct timestamp
|
|
||||||
sql = self.convert_timestamptz(scenario, exp_sql)
|
|
||||||
try:
|
try:
|
||||||
self.assertEquals(exp_sql, resp_sql)
|
self.assertEquals(exp_sql, resp_sql)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
@ -643,6 +624,38 @@ class ReverseEngineeredSQLTestCases(BaseTestGenerator):
|
|||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def preprocess_expected_sql(self, scenario, sql, resp_sql):
|
||||||
|
"""
|
||||||
|
This function preprocesses expected sql before comparing
|
||||||
|
it with response sql.
|
||||||
|
:param data: sql
|
||||||
|
:param data: resp_sql
|
||||||
|
:return:
|
||||||
|
"""
|
||||||
|
# Replace place holder <owner> with the current username
|
||||||
|
# used to connect to the database
|
||||||
|
if 'username' in self.server:
|
||||||
|
sql = sql.replace(self.JSON_PLACEHOLDERS['owner'],
|
||||||
|
self.server['username'])
|
||||||
|
# Convert timestamp with timezone from json file to the
|
||||||
|
# database server's correct timestamp
|
||||||
|
sql = self.convert_timestamptz(scenario, sql)
|
||||||
|
|
||||||
|
# extract password fields from response and replace in expected
|
||||||
|
# to match the response
|
||||||
|
if 'replace_password' in scenario:
|
||||||
|
password = ''
|
||||||
|
for line in resp_sql.split('\n'):
|
||||||
|
if 'PASSWORD' in line:
|
||||||
|
found = re.search("'([\w\W]*)'", line)
|
||||||
|
if found:
|
||||||
|
password = found.groups(0)[0]
|
||||||
|
break
|
||||||
|
|
||||||
|
sql = sql.replace(self.JSON_PLACEHOLDERS['password'], password)
|
||||||
|
|
||||||
|
return sql
|
||||||
|
|
||||||
def replace_placeholder_with_id(self, value):
|
def replace_placeholder_with_id(self, value):
|
||||||
"""
|
"""
|
||||||
This function is used to replace the place holder with id.
|
This function is used to replace the place holder with id.
|
||||||
|
Loading…
Reference in New Issue
Block a user