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