mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 17:09:03 +00:00
Merge pull request #42894 from gilbsgilbs/postgres-valid-until
Add support for PostgreSQL password expiration.
This commit is contained in:
commit
7d52bcee46
@ -886,8 +886,8 @@ def user_list(user=None, host=None, port=None, maintenance_db=None,
|
||||
for date_key in ('expiry time',):
|
||||
try:
|
||||
retrow[date_key] = datetime.datetime.strptime(
|
||||
row['date_key'], '%Y-%m-%d %H:%M:%S')
|
||||
except (ValueError, KeyError):
|
||||
row[date_key], '%Y-%m-%d %H:%M:%S')
|
||||
except ValueError:
|
||||
retrow[date_key] = None
|
||||
retrow['defaults variables'] = row['defaults variables']
|
||||
if return_password:
|
||||
@ -1025,6 +1025,7 @@ def _role_cmd_args(name,
|
||||
groups=None,
|
||||
replication=None,
|
||||
rolepassword=None,
|
||||
valid_until=None,
|
||||
db_role=None):
|
||||
if createuser is not None and superuser is None:
|
||||
superuser = createuser
|
||||
@ -1041,6 +1042,7 @@ def _role_cmd_args(name,
|
||||
encrypted = _DEFAULT_PASSWORDS_ENCRYPTION
|
||||
skip_passwd = False
|
||||
escaped_password = ''
|
||||
escaped_valid_until = ''
|
||||
if not (
|
||||
rolepassword is not None
|
||||
# first is passwd set
|
||||
@ -1058,6 +1060,10 @@ def _role_cmd_args(name,
|
||||
_maybe_encrypt_password(name,
|
||||
rolepassword.replace('\'', '\'\''),
|
||||
encrypted=encrypted))
|
||||
if isinstance(valid_until, six.string_types) and bool(valid_until):
|
||||
escaped_valid_until = '\'{0}\''.format(
|
||||
valid_until.replace('\'', '\'\''),
|
||||
)
|
||||
skip_superuser = False
|
||||
if bool(db_role) and bool(superuser) == bool(db_role['superuser']):
|
||||
skip_superuser = True
|
||||
@ -1081,6 +1087,10 @@ def _role_cmd_args(name,
|
||||
{'flag': 'PASSWORD', 'test': bool(rolepassword),
|
||||
'skip': skip_passwd,
|
||||
'addtxt': escaped_password},
|
||||
{'flag': 'VALID UNTIL',
|
||||
'test': bool(valid_until),
|
||||
'skip': valid_until is None,
|
||||
'addtxt': escaped_valid_until},
|
||||
)
|
||||
for data in flags:
|
||||
sub_cmd = _add_role_flag(sub_cmd, **data)
|
||||
@ -1110,6 +1120,7 @@ def _role_create(name,
|
||||
inherit=None,
|
||||
replication=None,
|
||||
rolepassword=None,
|
||||
valid_until=None,
|
||||
typ_='role',
|
||||
groups=None,
|
||||
runas=None):
|
||||
@ -1138,7 +1149,8 @@ def _role_create(name,
|
||||
superuser=superuser,
|
||||
groups=groups,
|
||||
replication=replication,
|
||||
rolepassword=rolepassword
|
||||
rolepassword=rolepassword,
|
||||
valid_until=valid_until
|
||||
))
|
||||
ret = _psql_prepare_and_run(['-c', sub_cmd],
|
||||
runas=runas, host=host, user=user, port=port,
|
||||
@ -1164,6 +1176,7 @@ def user_create(username,
|
||||
superuser=None,
|
||||
replication=None,
|
||||
rolepassword=None,
|
||||
valid_until=None,
|
||||
groups=None,
|
||||
runas=None):
|
||||
'''
|
||||
@ -1175,7 +1188,7 @@ def user_create(username,
|
||||
|
||||
salt '*' postgres.user_create 'username' user='user' \\
|
||||
host='hostname' port='port' password='password' \\
|
||||
rolepassword='rolepassword'
|
||||
rolepassword='rolepassword' valid_until='valid_until'
|
||||
'''
|
||||
return _role_create(username,
|
||||
typ_='user',
|
||||
@ -1194,6 +1207,7 @@ def user_create(username,
|
||||
superuser=superuser,
|
||||
replication=replication,
|
||||
rolepassword=rolepassword,
|
||||
valid_until=valid_until,
|
||||
groups=groups,
|
||||
runas=runas)
|
||||
|
||||
@ -1215,6 +1229,7 @@ def _role_update(name,
|
||||
superuser=None,
|
||||
replication=None,
|
||||
rolepassword=None,
|
||||
valid_until=None,
|
||||
groups=None,
|
||||
runas=None):
|
||||
'''
|
||||
@ -1250,6 +1265,7 @@ def _role_update(name,
|
||||
groups=groups,
|
||||
replication=replication,
|
||||
rolepassword=rolepassword,
|
||||
valid_until=valid_until,
|
||||
db_role=role
|
||||
))
|
||||
ret = _psql_prepare_and_run(['-c', sub_cmd],
|
||||
@ -1276,6 +1292,7 @@ def user_update(username,
|
||||
connlimit=None,
|
||||
replication=None,
|
||||
rolepassword=None,
|
||||
valid_until=None,
|
||||
groups=None,
|
||||
runas=None):
|
||||
'''
|
||||
@ -1287,7 +1304,7 @@ def user_update(username,
|
||||
|
||||
salt '*' postgres.user_update 'username' user='user' \\
|
||||
host='hostname' port='port' password='password' \\
|
||||
rolepassword='rolepassword'
|
||||
rolepassword='rolepassword' valid_until='valid_until'
|
||||
'''
|
||||
return _role_update(username,
|
||||
user=user,
|
||||
@ -1306,6 +1323,7 @@ def user_update(username,
|
||||
superuser=superuser,
|
||||
replication=replication,
|
||||
rolepassword=rolepassword,
|
||||
valid_until=valid_until,
|
||||
groups=groups,
|
||||
runas=runas)
|
||||
|
||||
|
@ -13,9 +13,10 @@ The postgres_users module is used to create and manage Postgres users.
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import Python libs
|
||||
import datetime
|
||||
import logging
|
||||
|
||||
# Import salt libs
|
||||
import logging
|
||||
|
||||
# Salt imports
|
||||
from salt.modules import postgres
|
||||
@ -45,6 +46,7 @@ def present(name,
|
||||
password=None,
|
||||
default_password=None,
|
||||
refresh_password=None,
|
||||
valid_until=None,
|
||||
groups=None,
|
||||
user=None,
|
||||
maintenance_db=None,
|
||||
@ -112,6 +114,9 @@ def present(name,
|
||||
This behaviour makes it possible to execute in environments without
|
||||
superuser access available, e.g. Amazon RDS for PostgreSQL
|
||||
|
||||
valid_until
|
||||
A date and time after which the role's password is no longer valid.
|
||||
|
||||
groups
|
||||
A string of comma separated groups the user should be in
|
||||
|
||||
@ -168,7 +173,6 @@ def present(name,
|
||||
if user_attr is not None:
|
||||
mode = 'update'
|
||||
|
||||
# The user is not present, make it!
|
||||
cret = None
|
||||
update = {}
|
||||
if mode == 'update':
|
||||
@ -199,6 +203,18 @@ def present(name,
|
||||
update['superuser'] = superuser
|
||||
if password is not None and (refresh_password or user_attr['password'] != password):
|
||||
update['password'] = True
|
||||
if valid_until is not None:
|
||||
valid_until_dt = __salt__['postgres.psql_query'](
|
||||
'SELECT \'{0}\'::timestamp(0) as dt;'.format(
|
||||
valid_until.replace('\'', '\'\'')),
|
||||
**db_args)[0]['dt']
|
||||
try:
|
||||
valid_until_dt = datetime.datetime.strptime(
|
||||
valid_until_dt, '%Y-%m-%d %H:%M:%S')
|
||||
except ValueError:
|
||||
valid_until_dt = None
|
||||
if valid_until_dt != user_attr['expiry time']:
|
||||
update['valid_until'] = valid_until
|
||||
if groups is not None:
|
||||
lgroups = groups
|
||||
if isinstance(groups, (six.string_types, six.text_type)):
|
||||
@ -228,6 +244,7 @@ def present(name,
|
||||
inherit=inherit,
|
||||
replication=replication,
|
||||
rolepassword=password,
|
||||
valid_until=valid_until,
|
||||
groups=groups,
|
||||
**db_args)
|
||||
else:
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
# Import python libs
|
||||
from __future__ import absolute_import, print_function
|
||||
import datetime
|
||||
import re
|
||||
|
||||
# Import Salt Testing libs
|
||||
@ -335,6 +336,7 @@ class PostgresTestCase(TestCase, LoaderModuleMockMixin):
|
||||
superuser=False,
|
||||
replication=False,
|
||||
rolepassword='test_role_pass',
|
||||
valid_until='2042-07-01',
|
||||
groups='test_groups',
|
||||
runas='foo'
|
||||
)
|
||||
@ -345,9 +347,10 @@ class PostgresTestCase(TestCase, LoaderModuleMockMixin):
|
||||
call = postgres._run_psql.call_args[0][0][14]
|
||||
self.assertTrue(re.match('CREATE ROLE "testuser"', call))
|
||||
for i in (
|
||||
'INHERIT NOCREATEDB NOCREATEROLE '
|
||||
'NOSUPERUSER NOREPLICATION LOGIN UNENCRYPTED PASSWORD'
|
||||
).split():
|
||||
'INHERIT', 'NOCREATEDB', 'NOCREATEROLE', 'NOSUPERUSER',
|
||||
'NOREPLICATION', 'LOGIN', 'UNENCRYPTED', 'PASSWORD',
|
||||
'VALID UNTIL',
|
||||
):
|
||||
self.assertTrue(i in call, '{0} not in {1}'.format(i, call))
|
||||
|
||||
def test_user_exists(self):
|
||||
@ -368,6 +371,7 @@ class PostgresTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'replication': None,
|
||||
'password': 'test_password',
|
||||
'connections': '-1',
|
||||
'expiry time': '',
|
||||
'defaults variables': None
|
||||
}])):
|
||||
ret = postgres.user_exists(
|
||||
@ -398,6 +402,7 @@ class PostgresTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'can login': 't',
|
||||
'replication': None,
|
||||
'connections': '-1',
|
||||
'expiry time': '2017-08-16 08:57:46',
|
||||
'defaults variables': None
|
||||
}])):
|
||||
ret = postgres.user_list(
|
||||
@ -416,7 +421,8 @@ class PostgresTestCase(TestCase, LoaderModuleMockMixin):
|
||||
'can create roles': True,
|
||||
'connections': None,
|
||||
'replication': None,
|
||||
'expiry time': None,
|
||||
'expiry time': datetime.datetime(
|
||||
2017, 8, 16, 8, 57, 46),
|
||||
'can login': True,
|
||||
'can update system catalogs': True,
|
||||
'groups': [],
|
||||
@ -464,6 +470,7 @@ class PostgresTestCase(TestCase, LoaderModuleMockMixin):
|
||||
login=True,
|
||||
replication=False,
|
||||
rolepassword='test_role_pass',
|
||||
valid_until='2017-07-01',
|
||||
groups='test_groups',
|
||||
runas='foo'
|
||||
)
|
||||
@ -475,7 +482,8 @@ class PostgresTestCase(TestCase, LoaderModuleMockMixin):
|
||||
re.match(
|
||||
'ALTER ROLE "test_username" WITH INHERIT NOCREATEDB '
|
||||
'NOCREATEROLE NOREPLICATION LOGIN '
|
||||
'UNENCRYPTED PASSWORD [\'"]{0,5}test_role_pass[\'"]{0,5};'
|
||||
'UNENCRYPTED PASSWORD [\'"]{0,5}test_role_pass[\'"]{0,5} '
|
||||
'VALID UNTIL \'2017-07-01\';'
|
||||
' GRANT "test_groups" TO "test_username"',
|
||||
postgres._run_psql.call_args[0][0][14]
|
||||
)
|
||||
|
@ -78,6 +78,7 @@ class PostgresUserTestCase(TestCase, LoaderModuleMockMixin):
|
||||
maintenance_db=None,
|
||||
login=None,
|
||||
password=None,
|
||||
valid_until=None,
|
||||
createdb=None)
|
||||
|
||||
def test_present__update(self):
|
||||
@ -126,6 +127,7 @@ class PostgresUserTestCase(TestCase, LoaderModuleMockMixin):
|
||||
maintenance_db=None,
|
||||
login=True,
|
||||
password=None,
|
||||
valid_until=None,
|
||||
createdb=None)
|
||||
|
||||
def test_present__no_update(self):
|
||||
|
Loading…
Reference in New Issue
Block a user