Merge pull request #4686 from bcoca/postgresql_user_pwds
postgresql_user now supports users w/o a password, encrypted passwords and expiration
This commit is contained in:
commit
8041735c56
1 changed files with 64 additions and 49 deletions
|
@ -43,8 +43,8 @@ options:
|
||||||
default: null
|
default: null
|
||||||
password:
|
password:
|
||||||
description:
|
description:
|
||||||
- set the user's password
|
- set the user's password, before 1.4 this was requried.
|
||||||
required: true
|
required: false
|
||||||
default: null
|
default: null
|
||||||
db:
|
db:
|
||||||
description:
|
description:
|
||||||
|
@ -90,6 +90,18 @@ options:
|
||||||
required: false
|
required: false
|
||||||
default: present
|
default: present
|
||||||
choices: [ "present", "absent" ]
|
choices: [ "present", "absent" ]
|
||||||
|
encrypted:
|
||||||
|
description:
|
||||||
|
- denotes if the password is already encrypted. boolean.
|
||||||
|
required: false
|
||||||
|
default: false
|
||||||
|
version_added: '1.4'
|
||||||
|
expires:
|
||||||
|
description:
|
||||||
|
- sets the user's password expiration.
|
||||||
|
required: false
|
||||||
|
default: null
|
||||||
|
version_added: '1.4'
|
||||||
notes:
|
notes:
|
||||||
- The default authentication assumes that you are either logging in as or
|
- The default authentication assumes that you are either logging in as or
|
||||||
sudo'ing to the postgres account on the host.
|
sudo'ing to the postgres account on the host.
|
||||||
|
@ -121,6 +133,9 @@ EXAMPLES = '''
|
||||||
|
|
||||||
# Example privileges string format
|
# Example privileges string format
|
||||||
INSERT,UPDATE/table:SELECT/anothertable:ALL
|
INSERT,UPDATE/table:SELECT/anothertable:ALL
|
||||||
|
|
||||||
|
# Remove an existing user's password
|
||||||
|
- postgresql_user: db=test user=test password=NULL
|
||||||
'''
|
'''
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
@ -146,15 +161,18 @@ def user_exists(cursor, user):
|
||||||
return cursor.rowcount > 0
|
return cursor.rowcount > 0
|
||||||
|
|
||||||
|
|
||||||
def user_add(cursor, user, password, role_attr_flags):
|
def user_add(cursor, user, password, role_attr_flags, encrypted, expires):
|
||||||
"""Create a new database user (role)."""
|
"""Create a new database user (role)."""
|
||||||
query = 'CREATE USER "%(user)s" WITH PASSWORD %%(password)s %(role_attr_flags)s' % {
|
query = 'CREATE USER "%(user)s"' % { "user": user}
|
||||||
"user": user, "role_attr_flags": role_attr_flags
|
if password is not None:
|
||||||
}
|
query = query + " WITH %(crypt)s PASSWORD '%(password)s'" % { "crypt": encrypted, "password": password }
|
||||||
cursor.execute(query, {"password": password})
|
if expires is not None:
|
||||||
|
query = query + " VALID UNTIL '%(expires)s'" % { "exipres": expires }
|
||||||
|
query = query + " " + role_attr_flags
|
||||||
|
cursor.execute(query)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def user_alter(cursor, user, password, role_attr_flags):
|
def user_alter(cursor, user, password, role_attr_flags, encrypted, expires):
|
||||||
"""Change user password and/or attributes. Return True if changed, False otherwise."""
|
"""Change user password and/or attributes. Return True if changed, False otherwise."""
|
||||||
changed = False
|
changed = False
|
||||||
|
|
||||||
|
@ -174,16 +192,18 @@ def user_alter(cursor, user, password, role_attr_flags):
|
||||||
# Grab current role attributes.
|
# Grab current role attributes.
|
||||||
current_role_attrs = cursor.fetchone()
|
current_role_attrs = cursor.fetchone()
|
||||||
|
|
||||||
|
alter = 'ALTER USER "%(user)s"' % {"user": user}
|
||||||
if password is not None:
|
if password is not None:
|
||||||
# Update the role attributes, including password.
|
alter = alter + " WITH %(crypt)s PASSWORD '%(password)s' %(flags)s" % {
|
||||||
alter = 'ALTER USER "%(user)s" WITH PASSWORD %%(password)s %(role_attr_flags)s' % {
|
"crypt": encrypted, "password": password, "flags": role_attr_flags
|
||||||
"user": user, "role_attr_flags": role_attr_flags
|
|
||||||
}
|
}
|
||||||
cursor.execute(alter, {"password": password})
|
elif role_attr_flags:
|
||||||
else:
|
alter = alter + ' WITH ' + role_attr_flags
|
||||||
# Update the role attributes, excluding password.
|
if expires is not None:
|
||||||
alter = "ALTER USER \"%(user)s\" WITH %(role_attr_flags)s"
|
alter = alter + " VALID UNTIL '%(expires)s'" % { "exipres": expires }
|
||||||
cursor.execute(alter % {"user": user, "role_attr_flags": role_attr_flags})
|
|
||||||
|
cursor.execute(alter)
|
||||||
|
|
||||||
# Grab new role attributes.
|
# Grab new role attributes.
|
||||||
cursor.execute(select, {"user": user})
|
cursor.execute(select, {"user": user})
|
||||||
new_role_attrs = cursor.fetchone()
|
new_role_attrs = cursor.fetchone()
|
||||||
|
@ -383,8 +403,10 @@ def main():
|
||||||
priv=dict(default=None),
|
priv=dict(default=None),
|
||||||
db=dict(default=''),
|
db=dict(default=''),
|
||||||
port=dict(default='5432'),
|
port=dict(default='5432'),
|
||||||
fail_on_user=dict(default='yes'),
|
fail_on_user=dict(type='bool', choices=BOOLEANS, default='yes'),
|
||||||
role_attr_flags=dict(default='')
|
role_attr_flags=dict(default=''),
|
||||||
|
encrypted=dict(type='bool', choices=BOOLEANS, default='no'),
|
||||||
|
expires=dict(default=None)
|
||||||
),
|
),
|
||||||
supports_check_mode = True
|
supports_check_mode = True
|
||||||
)
|
)
|
||||||
|
@ -392,13 +414,18 @@ def main():
|
||||||
user = module.params["user"]
|
user = module.params["user"]
|
||||||
password = module.params["password"]
|
password = module.params["password"]
|
||||||
state = module.params["state"]
|
state = module.params["state"]
|
||||||
fail_on_user = module.params["fail_on_user"] == 'yes'
|
fail_on_user = module.params["fail_on_user"]
|
||||||
db = module.params["db"]
|
db = module.params["db"]
|
||||||
if db == '' and module.params["priv"] is not None:
|
if db == '' and module.params["priv"] is not None:
|
||||||
module.fail_json(msg="privileges require a database to be specified")
|
module.fail_json(msg="privileges require a database to be specified")
|
||||||
privs = parse_privs(module.params["priv"], db)
|
privs = parse_privs(module.params["priv"], db)
|
||||||
port = module.params["port"]
|
port = module.params["port"]
|
||||||
role_attr_flags = parse_role_attrs(module.params["role_attr_flags"])
|
role_attr_flags = parse_role_attrs(module.params["role_attr_flags"])
|
||||||
|
if module.params["encrypted"]:
|
||||||
|
encrypted = "ENCRYPTED"
|
||||||
|
else:
|
||||||
|
encrypted = "UNENCRYPTED"
|
||||||
|
expires = module.params["expires"]
|
||||||
|
|
||||||
if not postgresqldb_found:
|
if not postgresqldb_found:
|
||||||
module.fail_json(msg="the python psycopg2 module is required")
|
module.fail_json(msg="the python psycopg2 module is required")
|
||||||
|
@ -426,32 +453,17 @@ def main():
|
||||||
user_removed = False
|
user_removed = False
|
||||||
|
|
||||||
if state == "present":
|
if state == "present":
|
||||||
|
|
||||||
if user_exists(cursor, user):
|
if user_exists(cursor, user):
|
||||||
if module.check_mode:
|
changed = user_alter(cursor, user, password, role_attr_flags, encrypted, expires)
|
||||||
kw['changed'] = True
|
|
||||||
module.exit_json(**kw)
|
|
||||||
|
|
||||||
changed = user_alter(cursor, user, password, role_attr_flags)
|
|
||||||
else:
|
else:
|
||||||
if password is None:
|
changed = user_add(cursor, user, password, role_attr_flags, encrypted, expires)
|
||||||
msg = "password parameter required when adding a user"
|
|
||||||
module.fail_json(msg=msg)
|
|
||||||
|
|
||||||
if module.check_mode:
|
|
||||||
kw['changed'] = True
|
|
||||||
module.exit_json(**kw)
|
|
||||||
|
|
||||||
changed = user_add(cursor, user, password, role_attr_flags)
|
|
||||||
changed = grant_privileges(cursor, user, privs) or changed
|
changed = grant_privileges(cursor, user, privs) or changed
|
||||||
else:
|
else:
|
||||||
|
|
||||||
if user_exists(cursor, user):
|
if user_exists(cursor, user):
|
||||||
if module.check_mode:
|
if module.check_mode:
|
||||||
kw['changed'] = True
|
changed = True
|
||||||
kw['user_removed'] = True
|
kw['user_removed'] = True
|
||||||
module.exit_json(**kw)
|
else:
|
||||||
|
|
||||||
changed = revoke_privileges(cursor, user, privs)
|
changed = revoke_privileges(cursor, user, privs)
|
||||||
user_removed = user_delete(cursor, user)
|
user_removed = user_delete(cursor, user)
|
||||||
changed = changed or user_removed
|
changed = changed or user_removed
|
||||||
|
@ -461,6 +473,9 @@ def main():
|
||||||
kw['user_removed'] = user_removed
|
kw['user_removed'] = user_removed
|
||||||
|
|
||||||
if changed:
|
if changed:
|
||||||
|
if module.check_mode:
|
||||||
|
db_connection.rollback()
|
||||||
|
else:
|
||||||
db_connection.commit()
|
db_connection.commit()
|
||||||
|
|
||||||
kw['changed'] = changed
|
kw['changed'] = changed
|
||||||
|
|
Loading…
Reference in a new issue