diff --git a/example-tasks/main.yml b/example-tasks/main.yml index de21eac..beb2e8a 100644 --- a/example-tasks/main.yml +++ b/example-tasks/main.yml @@ -22,7 +22,9 @@ mode: grant # ["grant", "revoke"] role: x_role permission: all # ["all", "alter", "drop", "select", "modify", "authorise", "describe", "execute"] - keyspace: "mykeyspace" + keyspaces: + - mykeyspace1 + - mykeyspace2 all_keyspaces: "False" - name: grant roles to users (aka roles to roles) @@ -33,4 +35,4 @@ login_hosts: localhost login_user: cassandra - login_password: cassandra \ No newline at end of file + login_password: cassandra diff --git a/library/__init__.py b/library/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/library/cassandra_grant.py b/library/cassandra_grant.py index 2e94b8e..8f420cc 100644 --- a/library/cassandra_grant.py +++ b/library/cassandra_grant.py @@ -19,12 +19,12 @@ - what permission to grant required: true choices: ["all", "create", "alter", "drop", "select", "modify", "authorize"] - keyspace: + keyspaces: description: - required if `all_keyspaces` == false - ignored if `inherit_role` is set required: false - default: false + default: [] all_keyspaces: description: - if true, `on` is ignored and the `what` is granted to all keyspaces @@ -74,7 +74,7 @@ - cassandra_grant: permission='select' all_keyspaces=True role=read_only login_hosts=localhost login_pass=cassandra login_user=cassandra # Revoke modify permission to foo keyspace -- cassandra_grant: mode=revoke permission=modify keyspace=foo role=no_modify_foo login_hosts=localhost login_pass=cassandra login_user=cassandra +- cassandra_grant: mode=revoke permission=modify keyspaces=[foo,bar] role=no_modify_foo login_hosts=localhost login_pass=cassandra login_user=cassandra # Inherit roles - cassandra_grant: mode=grant inherit_role=read_only role=my_user_role login_hosts=localhost login_pass=cassandra login_user=cassandra @@ -141,7 +141,7 @@ def assign_role(session, check_mode, is_revoke, inherit_role, role): return True -def grant_role_permission(session, in_check_mode, is_revoke, permission, all_keyspaces, keyspace, role): +def grant_role_permission(session, in_check_mode, is_revoke, permission, all_keyspaces, keyspaces, role): permission = permission.upper() if is_revoke and all_keyspaces: # revoking for all keyspaces @@ -151,10 +151,18 @@ def grant_role_permission(session, in_check_mode, is_revoke, permission, all_key query = GRANT_PERMISSION_TO_ROLE_FOR_ALL_KESYPACES_FORMAT.format(permission=permission) elif is_revoke: # revoking for a specific keyspace - query = REVOKE_PERMISSION_FROM_ROLE_FOR_KESYPACE_FORMAT.format(permission=permission, keyspace=keyspace) + for keyspace in keyspaces: + query = REVOKE_PERMISSION_FROM_ROLE_FOR_KESYPACE_FORMAT.format(permission=permission, keyspace=keyspace) + if not in_check_mode: + session.execute(query, {'role': role}) + return True else: # granting for a specific keyspace - query = GRANT_PERMISSION_TO_ROLE_FOR_KESYPACE_FORMAT.format(permission=permission, keyspace=keyspace) + for keyspace in keyspaces: + query = GRANT_PERMISSION_TO_ROLE_FOR_KESYPACE_FORMAT.format(permission=permission, keyspace=keyspace) + if not in_check_mode: + session.execute(query, {'role': role}) + return True if not in_check_mode: session.execute(query, {'role': role}) @@ -163,10 +171,10 @@ def grant_role_permission(session, in_check_mode, is_revoke, permission, all_key return True -def grant_access(session, in_check_mode, permission, role, inherit_role, keyspace, all_keyspaces, mode): - if keyspace and all_keyspaces: +def grant_access(session, in_check_mode, permission, role, inherit_role, keyspaces, all_keyspaces, mode): + if keyspaces and all_keyspaces: raise Exception("Specify a keyspace or all keyspaces, not both") - if keyspace and inherit_role: + if keyspaces and inherit_role: raise Exception("If you are inheriting a role you can't specify a keyspace") if all_keyspaces and inherit_role: raise Exception("If you are inheriting a role you can't specify all keyspaces") @@ -177,7 +185,7 @@ def grant_access(session, in_check_mode, permission, role, inherit_role, keyspac if inherit_role: return assign_role(session, in_check_mode, is_revoke, inherit_role, role) else: - return grant_role_permission(session, in_check_mode, is_revoke, permission, all_keyspaces, keyspace, role) + return grant_role_permission(session, in_check_mode, is_revoke, permission, all_keyspaces, keyspaces, role) def main(): @@ -212,10 +220,10 @@ def main(): 'required': False, 'default': None }, - 'keyspace': { + 'keyspaces': { 'required': False, - 'default': None, - 'type': 'str' + 'default': [], + 'type': 'list' }, 'all_keyspaces': { 'default': False, @@ -224,7 +232,12 @@ def main(): 'mode': { 'default': "grant", 'choices': ["grant", "revoke"] - } + }, + 'protocol': { + 'type': 'int', + 'default': 3, + 'required': False, + }, }, supports_check_mode=True ) @@ -235,9 +248,10 @@ def main(): permission = module.params["permission"] role = module.params["role"] inherit_role = module.params["inherit_role"] - keyspace = module.params["keyspace"] + keyspaces = module.params["keyspaces"] all_keyspaces = module.params["all_keyspaces"] mode = module.params["mode"] + protocol = module.params['protocol'] if not cassandra_dep_found: module.fail_json(msg="the python cassandra-driver module is required") @@ -249,7 +263,7 @@ def main(): cluster = Cluster(login_hosts, port=login_port) else: auth_provider = PlainTextAuthProvider(username=login_user, password=login_password) - cluster = Cluster(login_hosts, auth_provider=auth_provider, protocol_version=2, port=login_port) + cluster = Cluster(login_hosts, auth_provider=auth_provider, protocol_version=protocol, port=login_port) session = cluster.connect() session.row_factory = dict_factory except Exception, e: @@ -258,7 +272,7 @@ def main(): % e) try: - changed = grant_access(session, module.check_mode, permission, role, inherit_role, keyspace, all_keyspaces, + changed = grant_access(session, module.check_mode, permission, role, inherit_role, keyspaces, all_keyspaces, mode) except Exception, e: module.fail_json(msg=str(e)) diff --git a/library/cassandra_role.py b/library/cassandra_role.py index 202fa25..993a399 100644 --- a/library/cassandra_role.py +++ b/library/cassandra_role.py @@ -21,7 +21,7 @@ alias: role password: description: - - Set the role's password. Setting password will always elicit a 'change' (even if is the same). + - Set the role's password. required: true superuser: description: @@ -106,7 +106,11 @@ def role_save(session, check_mode, name, password, can_login, is_superuser): do_save(session, existing_role, is_superuser, name, password, can_login) new_user = get_role(session, name) - return bool(new_user != existing_role) + + if bool(password): + return not bool(existing_role) + else: + return bool(new_user != existing_role) def do_save(session, existing_role, is_superuser, name, password, can_login): @@ -174,7 +178,12 @@ def main(): 'state': { 'default': "present", 'choices': ["absent", "present"] - } + }, + 'protocol': { + 'type': 'int', + 'default': 3, + 'required': False, + }, }, supports_check_mode=True ) @@ -187,6 +196,7 @@ def main(): password = module.params["password"] superuser = module.params["superuser"] state = module.params["state"] + protocol = module.params['protocol'] if not cassandra_dep_found: module.fail_json(msg="the python cassandra-driver module is required") @@ -199,7 +209,7 @@ def main(): else: auth_provider = PlainTextAuthProvider(username=login_user, password=login_password) - cluster = Cluster(login_hosts, auth_provider=auth_provider, protocol_version=2, port=login_port) + cluster = Cluster(login_hosts, auth_provider=auth_provider, protocol_version=protocol, port=login_port) session = cluster.connect() session.row_factory = dict_factory except Exception, e: @@ -207,7 +217,11 @@ def main(): msg="unable to connect to cassandra, check login_user and login_password are correct. Exception message: %s" % e) + new_role = not bool(get_role(session, name)) + if state == "present": + if new_role: + changed = True try: changed = role_save(session, module.check_mode, name, password, enable_login, superuser) except Exception, e: @@ -217,7 +231,8 @@ def main(): changed = role_delete(session, module.check_mode, name) except Exception, e: module.fail_json(msg=str(e)) - module.exit_json(changed=changed, name=name) + + module.exit_json(changed=changed, role=name, new_role=new_role ) from ansible.module_utils.basic import *