|
|
|
@ -193,6 +193,44 @@ def load_mongocnf():
|
|
|
|
|
|
|
|
|
|
return creds
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def check_if_roles_changed(uinfo, roles, db_name):
|
|
|
|
|
# We must be aware of users which can read the oplog on a replicaset
|
|
|
|
|
# Such users must have access to the local DB, but since this DB does not store users credentials
|
|
|
|
|
# and is not synchronized among replica sets, the user must be stored on the admin db
|
|
|
|
|
# Therefore their structure is the following :
|
|
|
|
|
# {
|
|
|
|
|
# "_id" : "admin.oplog_reader",
|
|
|
|
|
# "user" : "oplog_reader",
|
|
|
|
|
# "db" : "admin", # <-- admin DB
|
|
|
|
|
# "roles" : [
|
|
|
|
|
# {
|
|
|
|
|
# "role" : "read",
|
|
|
|
|
# "db" : "local" # <-- local DB
|
|
|
|
|
# }
|
|
|
|
|
# ]
|
|
|
|
|
# }
|
|
|
|
|
|
|
|
|
|
def make_sure_roles_are_a_list_of_dict(roles, db_name):
|
|
|
|
|
output = list()
|
|
|
|
|
for role in roles:
|
|
|
|
|
if isinstance(role, basestring):
|
|
|
|
|
new_role = { "role": role, "db": db_name }
|
|
|
|
|
output.append(new_role)
|
|
|
|
|
else:
|
|
|
|
|
output.append(role)
|
|
|
|
|
return output
|
|
|
|
|
|
|
|
|
|
roles_as_list_of_dict = make_sure_roles_are_a_list_of_dict(roles, db_name)
|
|
|
|
|
uinfo_roles = uinfo.get('roles', [])
|
|
|
|
|
|
|
|
|
|
if sorted(roles_as_list_of_dict) == sorted(uinfo_roles):
|
|
|
|
|
return False
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# =========================================
|
|
|
|
|
# Module execution.
|
|
|
|
|
#
|
|
|
|
@ -265,7 +303,7 @@ def main():
|
|
|
|
|
uinfo = user_find(client, user, db_name)
|
|
|
|
|
if update_password != 'always' and uinfo:
|
|
|
|
|
password = None
|
|
|
|
|
if list(map((lambda x: x['role']), uinfo.get('roles', []))) == roles:
|
|
|
|
|
if not check_if_roles_changed(uinfo, roles, db_name):
|
|
|
|
|
module.exit_json(changed=False, user=user)
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|