Пример #1
0
def find_service(module, name, netbiosname):
    _args = {
        "all": True,
    }

    # Search for a SMB/cifs service.
    if netbiosname is not None:
        _result = api_command(module, "service_find", to_text(netbiosname),
                              _args)

        for _res_find in _result.get('result', []):
            for uid in _res_find.get('uid', []):
                if uid.startswith("%s$@" % netbiosname):
                    return _res_find

    try:
        _result = api_command(module, "service_show", to_text(name), _args)
    except ipalib.errors.NotFound:
        return None

    if "result" in _result:
        _res = _result["result"]
        certs = _res.get("usercertificate")
        if certs is not None:
            _res["usercertificate"] = [
                encode_certificate(cert) for cert in certs
            ]
        return _res
    else:
        return None
Пример #2
0
def process_commands(module, commands):
    """Process the list of IPA API commands."""
    errors = []
    exit_args = {}
    changed = False

    # Check mode exit
    if module.check_mode:
        return len(commands) > 0, exit_args

    for name, command, args in commands:
        try:
            result = api_command(module, command, name, args)
            if "completed" in result:
                if result["completed"] > 0:
                    changed = True
            else:
                changed = True

            errors = process_command_failures(command, result)
        except Exception as exception:  # pylint: disable=broad-except
            module.fail_json(msg="%s: %s: %s" %
                             (command, name, str(exception)))

    if errors:
        module.fail_json(msg=", ".join(errors))

    return changed, exit_args
Пример #3
0
def change_password(module, res_find, password, password_file, new_password,
                    new_password_file):
    """
    Change the password of a symmetric vault.

    To change the password of a vault, it is needed to retrieve the stored
    data with the current password, and store the data again, with the new
    password, forcing it to override the old one.
    """
    # verify parameters.
    if not any([new_password, new_password_file]):
        return []
    if res_find["ipavaulttype"][0] != "symmetric":
        module.fail_json(msg="Cannot change password of `%s` vault." %
                         res_find["ipavaulttype"])

    # prepare arguments to retrieve data.
    name = res_find["cn"][0]
    args = {}
    if password:
        args["password"] = password
    if password_file:
        args["password"] = password_file
    # retrieve current stored data
    result = api_command(module, 'vault_retrieve', name, args)
    args['data'] = result['result']['data']

    # modify arguments to store data with new password.
    if password:
        args["password"] = new_password
    if password_file:
        args["password"] = new_password_file
    args["override_password"] = True
    # return the command to store data with the new password.
    return [(name, "vault_archive", args)]
Пример #4
0
def find_dnsrecord(module, dnszone, name, **records):
    """Find a DNS record based on its name (idnsname)."""
    _args = {record: value for record, value in records.items()}
    _args["all"] = True
    if name != '@':
        _args['idnsname'] = to_text(name)

    try:
        _result = api_command(module, "dnsrecord_find", to_text(dnszone),
                              _args)
    except ipalib.errors.NotFound:
        return None

    if len(_result["result"]) > 1 and name != '@':
        module.fail_json(msg="There is more than one dnsrecord for '%s',"
                         " zone '%s'" % (name, dnszone))
    else:
        if len(_result["result"]) == 1:
            return _result["result"][0]
        else:
            for _res in _result["result"]:
                if 'idnsname' in _res:
                    for x in _res['idnsname']:
                        if '@' == to_text(x):
                            return _res
    return None
Пример #5
0
def add_trust(module, realm, args):
    _args = args

    _result = api_command(module, "trust_add", realm, _args)

    if "cn" not in _result["result"]:
        module.fail_json(msg="Trust add has failed for '%s'" % (realm))
Пример #6
0
def find_automember(module, name, grouping):
    _args = {"all": True, "type": to_text(grouping)}

    try:
        _result = api_command(module, "automember_show", to_text(name), _args)
    except ipalib_errors.NotFound:
        return None
    return _result["result"]
Пример #7
0
def del_trust(module, realm):
    _args = {}

    _result = api_command(module, "trust_del", realm, _args)
    if len(_result["result"]["failed"]) > 0:
        module.fail_json(msg="Trust deletion has failed for '%s'" % (realm))
    else:
        return None
Пример #8
0
def find_sudocmdgroup(module, name):
    args = {"all": True}

    try:
        _result = api_command(module, "sudocmdgroup_show", to_text(name), args)
    except ipalib.errors.NotFound:
        return None
    else:
        return _result["result"]
Пример #9
0
def find_permission(module, name):
    """Find if a permission with the given name already exist."""
    try:
        _result = api_command(module, "permission_show", name, {"all": True})
    except Exception:  # pylint: disable=broad-except
        # An exception is raised if permission name is not found.
        return None
    else:
        return _result["result"]
Пример #10
0
def find_dnsforwardzone(module, name):
    _args = {"all": True, "idnsname": name}
    _result = api_command(module, "dnsforwardzone_find", name, _args)

    if len(_result["result"]) > 1:
        module.fail_json(msg="There is more than one dnsforwardzone '%s'" %
                         (name))
    elif len(_result["result"]) == 1:
        return _result["result"][0]
    else:
        return None
def find_cn(module, suffix, name):
    _args = {
        "cn": to_text(name),
    }
    _result = api_command(module, "topologysegment_find", to_text(suffix),
                          _args)
    if len(_result["result"]) > 1:
        module.fail_json(msg="CN '%s' is not unique for suffix '%s'" %
                         (name, suffix))
    elif len(_result["result"]) == 1:
        return _result["result"][0]
    else:
        return None
Пример #12
0
def find_dnsrecord(module, dnszone, name):
    """Find a DNS record based on its name (idnsname)."""
    _args = {
        "all": True,
        "idnsname": to_text(name),
    }

    try:
        _result = api_command(
            module, "dnsrecord_show", to_text(dnszone), _args)
    except ipalib.errors.NotFound:
        return None

    return _result["result"]
Пример #13
0
def find_hostgroup(module, name):
    _args = {
        "all": True,
        "cn": name,
    }

    _result = api_command(module, "hostgroup_find", name, _args)

    if len(_result["result"]) > 1:
        module.fail_json(msg="There is more than one hostgroup '%s'" % (name))
    elif len(_result["result"]) == 1:
        return _result["result"][0]
    else:
        return None
Пример #14
0
def find_sudorule(module, name):
    _args = {
        "all": True,
        "cn": name,
    }

    _result = api_command(module, "sudorule_find", name, _args)

    if len(_result["result"]) > 1:
        module.fail_json(msg="There is more than one sudorule '%s'" % (name))
    elif len(_result["result"]) == 1:
        return _result["result"][0]

    return None
Пример #15
0
def find_hbacsvc(module, name):
    _args = {
        "all": True,
        "cn": to_text(name),
    }

    _result = api_command(module, "hbacsvc_find", to_text(name), _args)

    if len(_result["result"]) > 1:
        module.fail_json(msg="There is more than one hbacsvc '%s'" % (name))
    elif len(_result["result"]) == 1:
        return _result["result"][0]
    else:
        return None
Пример #16
0
def find_trust(module, realm):
    _args = {
        "all": True,
        "cn": realm,
    }

    _result = api_command(module, "trust_find", realm, _args)

    if len(_result["result"]) > 1:
        module.fail_json(msg="There is more than one realm '%s'" % (realm))
    elif len(_result["result"]) == 1:
        return _result["result"][0]
    else:
        return None
def find_left_right(module, suffix, left, right):
    _args = {
        "iparepltoposegmentleftnode": to_text(left),
        "iparepltoposegmentrightnode": to_text(right),
    }
    _result = api_command(module, "topologysegment_find", to_text(suffix),
                          _args)
    if len(_result["result"]) > 1:
        module.fail_json(
            msg="Combination of left node '%s' and right node '%s' is "
            "not unique for suffix '%s'" % (left, right, suffix))
    elif len(_result["result"]) == 1:
        return _result["result"][0]
    else:
        return None
Пример #18
0
def find_pwpolicy(module, name):
    _args = {
        "all": True,
        "cn": to_text(name),
    }

    _result = api_command(module, "pwpolicy_find", to_text(name), _args)

    if len(_result["result"]) > 1:
        module.fail_json(
            msg="There is more than one pwpolicy '%s'" % (name))
    elif len(_result["result"]) == 1:
        return _result["result"][0]

    return None
Пример #19
0
def find_user(module, name, preserved=False):
    _args = {
        "all": True,
        "uid": to_text(name),
    }
    if preserved:
        _args["preserved"] = preserved

    _result = api_command(module, "user_find", to_text(name), _args)

    if len(_result["result"]) > 1:
        module.fail_json(msg="There is more than one user '%s'" % (name))
    elif len(_result["result"]) == 1:
        return _result["result"][0]
    else:
        return None
Пример #20
0
def find_service(module, name):
    _args = {
        "all": True,
    }

    _result = api_command(module, "service_find", to_text(name), _args)

    if len(_result["result"]) > 1:
        module.fail_json(
            msg="There is more than one service '%s'" % (name))
    elif len(_result["result"]) == 1:
        _res = _result["result"][0]
        certs = _res.get("usercertificate")
        if certs is not None:
            _res["usercertificate"] = [encode_certificate(cert) for
                                       cert in certs]
        return _res
    else:
        return None
Пример #21
0
def get_stored_data(module, res_find, args):
    """Retrieve data stored in the vault."""
    # prepare arguments to retrieve data.
    name = res_find["cn"][0]
    copy_args = []
    if res_find['ipavaulttype'][0] == "symmetric":
        copy_args = ["password", "password_file"]
    if res_find['ipavaulttype'][0] == "asymmetric":
        copy_args = ["private_key", "private_key_file"]

    pwdargs = {arg: args[arg] for arg in copy_args if arg in args}

    # retrieve vault stored data
    try:
        result = api_command(module, 'vault_retrieve', name, pwdargs)
    except NotFound:
        return None

    return result['result'].get('data')
Пример #22
0
def find_service(module, name):
    _args = {
        "all": True,
    }

    try:
        _result = api_command(module, "service_show", to_text(name), _args)
    except ipalib_errors.NotFound:
        return None

    if "result" in _result:
        _res = _result["result"]
        certs = _res.get("usercertificate")
        if certs is not None:
            _res["usercertificate"] = [
                encode_certificate(cert) for cert in certs
            ]
        return _res

    return None
Пример #23
0
def find_vault(module, name, username, service, shared):
    _args = {
        "all": True,
        "cn": name,
    }

    if username is not None:
        _args['username'] = username
    elif service is not None:
        _args['service'] = service
    else:
        _args['shared'] = shared

    _result = api_command(module, "vault_find", name, _args)

    if len(_result["result"]) > 1:
        module.fail_json(msg="There is more than one vault '%s'" % (name))
    if len(_result["result"]) == 1:
        return _result["result"][0]

    return None
Пример #24
0
def main():
    ansible_module = AnsibleModule(
        argument_spec=dict(
            # general
            ipaadmin_principal=dict(type="str", default="admin"),
            ipaadmin_password=dict(type="str", required=False, no_log=True),
            name=dict(type="list", aliases=["cn"], default=None,
                      required=True),
            # present
            right=dict(type="list",
                       aliases=["ipapermright"],
                       default=None,
                       required=False,
                       choices=[
                           "read", "search", "compare", "write", "add",
                           "delete", "all"
                       ]),
            attrs=dict(type="list", default=None, required=False),
            # Note: bindtype has a default of permission for Adds.
            bindtype=dict(type="str",
                          aliases=["ipapermbindruletype"],
                          default=None,
                          require=False,
                          choices=["permission", "all", "anonymous", "self"]),
            subtree=dict(type="str",
                         aliases=["ipapermlocation"],
                         default=None,
                         required=False),
            extra_target_filter=dict(type="list",
                                     aliases=["filter", "extratargetfilter"],
                                     default=None,
                                     required=False),
            rawfilter=dict(type="list",
                           aliases=["ipapermtargetfilter"],
                           default=None,
                           required=False),
            target=dict(type="str",
                        aliases=["ipapermtarget"],
                        default=None,
                        required=False),
            targetto=dict(type="str",
                          aliases=["ipapermtargetto"],
                          default=None,
                          required=False),
            targetfrom=dict(type="str",
                            aliases=["ipapermtargetfrom"],
                            default=None,
                            required=False),
            memberof=dict(type="list", default=None, required=False),
            targetgroup=dict(type="str", default=None, required=False),
            object_type=dict(type="str",
                             aliases=["type"],
                             default=None,
                             required=False),
            no_members=dict(type=bool, default=None, require=False),
            rename=dict(type="str", default=None, required=False),
            privilege=dict(type="list", default=None, required=False),
            action=dict(type="str",
                        default="permission",
                        choices=["member", "permission"]),
            # state
            state=dict(type="str",
                       default="present",
                       choices=["present", "absent", "renamed"]),
        ),
        supports_check_mode=True,
    )

    ansible_module._ansible_debug = True

    # Get parameters

    # general
    ipaadmin_principal = module_params_get(ansible_module,
                                           "ipaadmin_principal")
    ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password")
    names = module_params_get(ansible_module, "name")

    # present
    right = module_params_get(ansible_module, "right")
    attrs = module_params_get(ansible_module, "attrs")
    bindtype = module_params_get(ansible_module, "bindtype")
    subtree = module_params_get(ansible_module, "subtree")
    extra_target_filter = module_params_get(ansible_module,
                                            "extra_target_filter")
    rawfilter = module_params_get(ansible_module, "rawfilter")
    target = module_params_get(ansible_module, "target")
    targetto = module_params_get(ansible_module, "targetto")
    targetfrom = module_params_get(ansible_module, "targetfrom")
    memberof = module_params_get(ansible_module, "memberof")
    targetgroup = module_params_get(ansible_module, "targetgroup")
    object_type = module_params_get(ansible_module, "object_type")
    no_members = module_params_get(ansible_module, "no_members")
    rename = module_params_get(ansible_module, "rename")
    privilege = module_params_get(ansible_module, "privilege")
    action = module_params_get(ansible_module, "action")

    # state
    state = module_params_get(ansible_module, "state")

    # Check parameters

    invalid = []

    if state == "present":
        if len(names) != 1:
            ansible_module.fail_json(
                msg="Only one permission can be added at a time.")
        if action == "member":
            invalid = [
                "right", "attrs", "bindtype", "subtree", "extra_target_filter",
                "rawfilter", "target", "targetto", "targetfrom", "memberof",
                "targetgroup", "object_type", "rename"
            ]

    if state == "renamed":
        if len(names) != 1:
            ansible_module.fail_json(
                msg="Only one permission can be renamed at a time.")
        if action == "member":
            ansible_module.fail_json(msg="Member Privileges cannot be renamed")
        invalid = [
            "right", "attrs", "bindtype", "subtree", "extra_target_filter",
            "rawfilter", "target", "targetto", "targetfrom", "memberof",
            "targetgroup", "object_type", "no_members"
        ]

    if state == "absent":
        if len(names) < 1:
            ansible_module.fail_json(msg="No name given.")
        invalid = [
            "right", "attrs", "bindtype", "subtree", "extra_target_filter",
            "rawfilter", "target", "targetto", "targetfrom", "memberof",
            "targetgroup", "object_type", "no_members", "rename"
        ]
        if action == "permission":
            invalid.append("privilege")

    for x in invalid:
        if vars()[x] is not None:
            ansible_module.fail_json(
                msg="Argument '%s' can not be used with action "
                "'%s' and state '%s'" % (x, action, state))

    if bindtype == "self" and api_check_ipa_version("<", "4.8.7"):
        ansible_module.fail_json(
            msg="Bindtype 'self' is not supported by your IPA version.")

    # Init

    changed = False
    exit_args = {}
    ccache_dir = None
    ccache_name = None
    try:
        if not valid_creds(ansible_module, ipaadmin_principal):
            ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
                                                 ipaadmin_password)
        api_connect()

        commands = []
        for name in names:
            # Make sure permission exists
            res_find = find_permission(ansible_module, name)

            # Create command
            if state == "present":
                # Generate args
                args = gen_args(right, attrs, bindtype, subtree,
                                extra_target_filter, rawfilter, target,
                                targetto, targetfrom, memberof, targetgroup,
                                object_type, no_members, rename)

                no_members_value = False

                if no_members is not None:
                    no_members_value = no_members

                if action == "permission":
                    # Found the permission
                    if res_find is not None:
                        # For all settings is args, check if there are
                        # different settings in the find result.
                        # If yes: modify
                        if not compare_args_ipa(ansible_module, args,
                                                res_find):
                            commands.append([name, "permission_mod", args])
                    else:
                        commands.append([name, "permission_add", args])

                    member_args = gen_member_args(privilege)
                    if not compare_args_ipa(ansible_module, member_args,
                                            res_find):

                        # Generate addition and removal lists
                        privilege_add, privilege_del = gen_add_del_lists(
                            privilege, res_find.get("member_privilege"))

                        # Add members
                        if len(privilege_add) > 0:
                            commands.append([
                                name, "permission_add_member", {
                                    "privilege": privilege_add,
                                    "no_members": no_members_value
                                }
                            ])
                        # Remove members
                        if len(privilege_del) > 0:
                            commands.append([
                                name, "permission_remove_member", {
                                    "privilege": privilege_del,
                                    "no_members": no_members_value
                                }
                            ])
                elif action == "member":
                    if res_find is None:
                        ansible_module.fail_json(msg="No permission '%s'" %
                                                 name)

                    if privilege is None:
                        ansible_module.fail_json(msg="No privilege given")

                    commands.append([
                        name, "permission_add_member", {
                            "privilege": privilege,
                            "no_members": no_members_value
                        }
                    ])
                else:
                    ansible_module.fail_json(msg="Unknown action '%s'" %
                                             action)
            elif state == "renamed":
                if action == "permission":
                    # Generate args
                    # Note: Only valid arg for rename is rename.
                    args = gen_args(right, attrs, bindtype, subtree,
                                    extra_target_filter, rawfilter, target,
                                    targetto, targetfrom, memberof,
                                    targetgroup, object_type, no_members,
                                    rename)

                    # Found the permission
                    if res_find is not None:
                        # For all settings is args, check if there are
                        # different settings in the find result.
                        # If yes: modify
                        if not compare_args_ipa(ansible_module, args,
                                                res_find):
                            commands.append([name, "permission_mod", args])
                    else:
                        ansible_module.fail_json(
                            msg="Permission not found, cannot rename")
                else:
                    ansible_module.fail_json(msg="Unknown action '%s'" %
                                             action)
            elif state == "absent":
                if action == "permission":
                    if res_find is not None:
                        commands.append([name, "permission_del", {}])

                elif action == "member":
                    if res_find is None:
                        ansible_module.fail_json(msg="No permission '%s'" %
                                                 name)

                    if privilege is None:
                        ansible_module.fail_json(msg="No privilege given")

                    commands.append([
                        name, "permission_remove_member", {
                            "privilege": privilege,
                        }
                    ])

            else:
                ansible_module.fail_json(msg="Unknown state '%s'" % state)

        # Execute commands

        for name, command, args in commands:
            try:
                result = api_command(ansible_module, command, name, args)
                if "completed" in result:
                    if result["completed"] > 0:
                        changed = True
                else:
                    changed = True
            except Exception as e:
                ansible_module.fail_json(msg="%s: %s: %s" %
                                         (command, name, str(e)))
            # Get all errors
            # All "already a member" and "not a member" failures in the
            # result are ignored. All others are reported.
            errors = []
            for failed_item in result.get("failed", []):
                failed = result["failed"][failed_item]
                for member_type in failed:
                    for member, failure in failed[member_type]:
                        if "already a member" in failure \
                           or "not a member" in failure:
                            continue
                        errors.append("%s: %s %s: %s" %
                                      (command, member_type, member, failure))
            if len(errors) > 0:
                ansible_module.fail_json(msg=", ".join(errors))

    except Exception as e:
        ansible_module.fail_json(msg=str(e))

    finally:
        temp_kdestroy(ccache_dir, ccache_name)

    # Done

    ansible_module.exit_json(changed=changed, **exit_args)
Пример #25
0
def main():
    ansible_module = AnsibleModule(
        argument_spec=dict(
            # general
            ipaadmin_principal=dict(type="str", default="admin"),
            ipaadmin_password=dict(type="str", required=False, no_log=True),
            name=dict(type="list", aliases=["cn"], default=None,
                      required=True),
            forwarders=dict(type="list",
                            default=None,
                            required=False,
                            aliases=["idnsforwarders"],
                            elements='dict',
                            options=dict(
                                ip_address=dict(type='str', required=True),
                                port=dict(type='int',
                                          required=False,
                                          default=None),
                            )),
            forwardpolicy=dict(type='str',
                               aliases=["idnsforwardpolicy"],
                               required=False,
                               choices=['only', 'first', 'none']),
            skip_overlap_check=dict(type='bool', required=False),
            permission=dict(type='bool', required=False,
                            aliases=['managedby']),
            action=dict(type="str",
                        default="dnsforwardzone",
                        choices=["member", "dnsforwardzone"]),
            # state
            state=dict(type='str',
                       default='present',
                       choices=['present', 'absent', 'enabled', 'disabled']),
        ),
        supports_check_mode=True,
    )

    ansible_module._ansible_debug = True

    # Get parameters
    ipaadmin_principal = module_params_get(ansible_module,
                                           "ipaadmin_principal")
    ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password")
    names = module_params_get(ansible_module, "name")
    action = module_params_get(ansible_module, "action")
    forwarders = forwarder_list(module_params_get(ansible_module,
                                                  "forwarders"))
    forwardpolicy = module_params_get(ansible_module, "forwardpolicy")
    skip_overlap_check = module_params_get(ansible_module,
                                           "skip_overlap_check")
    permission = module_params_get(ansible_module, "permission")
    state = module_params_get(ansible_module, "state")

    if state == 'present' and len(names) != 1:
        ansible_module.fail_json(
            msg="Only one dnsforwardzone can be added at a time.")
    if state == 'absent' and len(names) < 1:
        ansible_module.fail_json(msg="No name given.")

    # absent stae means delete if the action is NOT member but update if it is
    # if action is member then update an exisiting resource
    # and if action is not member then create a resource
    if state == "absent" and action == "dnsforwardzone":
        operation = "del"
    elif action == "member":
        operation = "update"
    else:
        operation = "add"

    if state in ["enabled", "disabled"]:
        if action == "member":
            ansible_module.fail_json(
                msg="Action `member` cannot be used with state `%s`" % (state))
        invalid = [
            "forwarders", "forwardpolicy", "skip_overlap_check", "permission"
        ]
        for x in invalid:
            if vars()[x] is not None:
                ansible_module.fail_json(
                    msg="Argument '%s' can not be used with action "
                    "'%s', state `%s`" % (x, action, state))
        wants_enable = (state == "enabled")

    if operation == "del":
        invalid = [
            "forwarders", "forwardpolicy", "skip_overlap_check", "permission"
        ]
        for x in invalid:
            if vars()[x] is not None:
                ansible_module.fail_json(
                    msg="Argument '%s' can not be used with action "
                    "'%s', state `%s`" % (x, action, state))

    changed = False
    exit_args = {}
    args = {}
    ccache_dir = None
    ccache_name = None
    is_enabled = "IGNORE"
    try:
        # we need to determine 3 variables
        # args = the values we want to change/set
        # command = the ipa api command to call del, add, or mod
        # is_enabled = is the current resource enabled (True)
        #             disabled (False) and do we care (IGNORE)

        if not valid_creds(ansible_module, ipaadmin_principal):
            ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
                                                 ipaadmin_password)
        api_connect()

        for name in names:
            commands = []
            command = None

            # Make sure forwardzone exists
            existing_resource = find_dnsforwardzone(ansible_module, name)

            # validate parameters
            if state == 'present':
                if existing_resource is None and not forwarders:
                    ansible_module.fail_json(msg='No forwarders specified.')

            if existing_resource is None:
                if operation == "add":
                    # does not exist but should be present
                    # determine args
                    args = gen_args(forwarders, forwardpolicy,
                                    skip_overlap_check)
                    # set command
                    command = "dnsforwardzone_add"
                    # enabled or disabled?

                elif operation == "update":
                    # does not exist and is updating
                    # trying to update something that doesn't exist, so error
                    ansible_module.fail_json(
                        msg="dnsforwardzone '%s' not found." % (name))

                elif operation == "del":
                    # there's nothnig to do.
                    continue

            else:  # existing_resource is not None
                if state != "absent":
                    if forwarders:
                        forwarders = list(
                            set(existing_resource["idnsforwarders"] +
                                forwarders))
                else:
                    if forwarders:
                        forwarders = list(
                            set(existing_resource["idnsforwarders"]) -
                            set(forwarders))

                if operation == "add":
                    # exists and should be present, has it changed?
                    # determine args
                    args = gen_args(forwarders, forwardpolicy,
                                    skip_overlap_check)
                    if 'skip_overlap_check' in args:
                        del args['skip_overlap_check']

                    # set command
                    if not compare_args_ipa(ansible_module, args,
                                            existing_resource):
                        command = "dnsforwardzone_mod"

                elif operation == "del":
                    # exists but should be absent
                    # set command
                    command = "dnsforwardzone_del"
                    args = {}

                elif operation == "update":
                    # exists and is updating
                    # calculate the new forwarders and mod
                    args = gen_args(forwarders, forwardpolicy,
                                    skip_overlap_check)
                    if "skip_overlap_check" in args:
                        del args['skip_overlap_check']

                    # command
                    if not compare_args_ipa(ansible_module, args,
                                            existing_resource):
                        command = "dnsforwardzone_mod"

            if state in ['enabled', 'disabled']:
                if existing_resource is not None:
                    is_enabled = existing_resource["idnszoneactive"][0]
                else:
                    ansible_module.fail_json(
                        msg="dnsforwardzone '%s' not found." % (name))

            # does the enabled state match what we want (if we care)
            if is_enabled != "IGNORE":
                if wants_enable and is_enabled != "TRUE":
                    commands.append([name, "dnsforwardzone_enable", {}])
                elif not wants_enable and is_enabled != "FALSE":
                    commands.append([name, "dnsforwardzone_disable", {}])

            # if command is set...
            if command is not None:
                commands.append([name, command, args])

            if permission is not None:
                if existing_resource is None:
                    managedby = None
                else:
                    managedby = existing_resource.get('managedby', None)
                if permission and managedby is None:
                    commands.append(
                        [name, 'dnsforwardzone_add_permission', {}])
                elif not permission and managedby is not None:
                    commands.append(
                        [name, 'dnsforwardzone_remove_permission', {}])

            for name, command, args in commands:
                api_command(ansible_module, command, name, args)
                changed = True

    except Exception as e:
        ansible_module.fail_json(msg=str(e))

    finally:
        temp_kdestroy(ccache_dir, ccache_name)

    # Done
    ansible_module.exit_json(changed=changed, dnsforwardzone=exit_args)
Пример #26
0
def main():
    ansible_module = AnsibleModule(
        argument_spec=dict(
            # general
            ipaadmin_principal=dict(type="str", default="admin"),
            ipaadmin_password=dict(type="str", required=False, no_log=True),
            name=dict(type="list", aliases=["cn"], default=None,
                      required=True),
            # present
            description=dict(type="str", default=None),
            nomembers=dict(required=False, type='bool', default=None),
            host=dict(required=False, type='list', default=None),
            hostgroup=dict(required=False, type='list', default=None),
            membermanager_user=dict(required=False, type='list', default=None),
            membermanager_group=dict(required=False, type='list',
                                     default=None),
            rename=dict(required=False,
                        type='str',
                        default=None,
                        aliases=["new_name"]),
            action=dict(type="str",
                        default="hostgroup",
                        choices=["member", "hostgroup"]),
            # state
            state=dict(type="str",
                       default="present",
                       choices=["present", "absent", "renamed"]),
        ),
        supports_check_mode=True,
    )

    ansible_module._ansible_debug = True

    # Get parameters

    # general
    ipaadmin_principal = module_params_get(ansible_module,
                                           "ipaadmin_principal")
    ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password")
    names = module_params_get(ansible_module, "name")

    # present
    description = module_params_get(ansible_module, "description")
    nomembers = module_params_get(ansible_module, "nomembers")
    host = module_params_get(ansible_module, "host")
    hostgroup = module_params_get(ansible_module, "hostgroup")
    membermanager_user = module_params_get(ansible_module,
                                           "membermanager_user")
    membermanager_group = module_params_get(ansible_module,
                                            "membermanager_group")
    rename = module_params_get(ansible_module, "rename")
    action = module_params_get(ansible_module, "action")
    # state
    state = module_params_get(ansible_module, "state")

    # Check parameters

    if state == "present":
        if len(names) != 1:
            ansible_module.fail_json(
                msg="Only one hostgroup can be added at a time.")
        invalid = ["rename"]
        if action == "member":
            invalid.extend(["description", "nomembers"])
        for x in invalid:
            if vars()[x] is not None:
                ansible_module.fail_json(
                    msg="Argument '%s' can not be used with action "
                    "'%s'" % (x, action))

    if state == "renamed":
        if len(names) != 1:
            ansible_module.fail_json(
                msg="Only one hostgroup can be added at a time.")
        if action == "member":
            ansible_module.fail_json(
                msg="Action '%s' can not be used with state '%s'" %
                (action, state))
        invalid = [
            "description", "nomembers", "host", "hostgroup",
            "membermanager_user", "membermanager_group"
        ]
        for x in invalid:
            if vars()[x] is not None:
                ansible_module.fail_json(
                    msg="Argument '%s' can not be used with state '%s'" %
                    (x, state))

    if state == "absent":
        if len(names) < 1:
            ansible_module.fail_json(msg="No name given.")
        invalid = ["description", "nomembers", "rename"]
        if action == "hostgroup":
            invalid.extend(["host", "hostgroup"])
        for x in invalid:
            if vars()[x] is not None:
                ansible_module.fail_json(
                    msg="Argument '%s' can not be used with state '%s'" %
                    (x, state))

    # Init

    changed = False
    exit_args = {}
    ccache_dir = None
    ccache_name = None
    try:
        if not valid_creds(ansible_module, ipaadmin_principal):
            ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
                                                 ipaadmin_password)
        api_connect()

        has_add_membermanager = api_check_command(
            "hostgroup_add_member_manager")
        if ((membermanager_user is not None or membermanager_group is not None)
                and not has_add_membermanager):
            ansible_module.fail_json(
                msg="Managing a membermanager user or group is not supported "
                "by your IPA version")
        has_mod_rename = api_check_param("hostgroup_mod", "rename")
        if not has_mod_rename and rename is not None:
            ansible_module.fail_json(
                msg="Renaming hostgroups is not supported by your IPA version")

        commands = []

        for name in names:
            # Make sure hostgroup exists
            res_find = find_hostgroup(ansible_module, name)

            # Create command
            if state == "present":
                # Generate args
                args = gen_args(description, nomembers, rename)

                if action == "hostgroup":
                    # Found the hostgroup
                    if res_find is not None:
                        # For all settings is args, check if there are
                        # different settings in the find result.
                        # If yes: modify
                        if not compare_args_ipa(ansible_module, args,
                                                res_find):
                            commands.append([name, "hostgroup_mod", args])
                    else:
                        commands.append([name, "hostgroup_add", args])
                        # Set res_find to empty dict for next step
                        res_find = {}

                    member_args = gen_member_args(host, hostgroup)
                    if not compare_args_ipa(ansible_module, member_args,
                                            res_find):
                        # Generate addition and removal lists
                        host_add, host_del = gen_add_del_lists(
                            host, res_find.get("member_host"))

                        hostgroup_add, hostgroup_del = gen_add_del_lists(
                            hostgroup, res_find.get("member_hostgroup"))

                        # Add members
                        if len(host_add) > 0 or len(hostgroup_add) > 0:
                            commands.append([
                                name, "hostgroup_add_member", {
                                    "host": host_add,
                                    "hostgroup": hostgroup_add,
                                }
                            ])
                        # Remove members
                        if len(host_del) > 0 or len(hostgroup_del) > 0:
                            commands.append([
                                name, "hostgroup_remove_member", {
                                    "host": host_del,
                                    "hostgroup": hostgroup_del,
                                }
                            ])

                    membermanager_user_add, membermanager_user_del = \
                        gen_add_del_lists(
                            membermanager_user,
                            res_find.get("membermanager_user")
                        )

                    membermanager_group_add, membermanager_group_del = \
                        gen_add_del_lists(
                            membermanager_group,
                            res_find.get("membermanager_group")
                        )

                    if has_add_membermanager:
                        # Add membermanager users and groups
                        if len(membermanager_user_add) > 0 or \
                           len(membermanager_group_add) > 0:
                            commands.append([
                                name, "hostgroup_add_member_manager", {
                                    "user": membermanager_user_add,
                                    "group": membermanager_group_add,
                                }
                            ])
                        # Remove member manager
                        if len(membermanager_user_del) > 0 or \
                           len(membermanager_group_del) > 0:
                            commands.append([
                                name, "hostgroup_remove_member_manager", {
                                    "user": membermanager_user_del,
                                    "group": membermanager_group_del,
                                }
                            ])

                elif action == "member":
                    if res_find is None:
                        ansible_module.fail_json(msg="No hostgroup '%s'" %
                                                 name)

                    # Ensure members are present
                    commands.append([
                        name, "hostgroup_add_member", {
                            "host": host,
                            "hostgroup": hostgroup,
                        }
                    ])

                    if has_add_membermanager:
                        # Add membermanager users and groups
                        if membermanager_user is not None or \
                           membermanager_group is not None:
                            commands.append([
                                name, "hostgroup_add_member_manager", {
                                    "user": membermanager_user,
                                    "group": membermanager_group,
                                }
                            ])

            elif state == "renamed":
                if res_find is not None:
                    if rename != name:
                        commands.append(
                            [name, "hostgroup_mod", {
                                "rename": rename
                            }])
                else:
                    # If a hostgroup with the desired name exists, do nothing.
                    new_find = find_hostgroup(ansible_module, rename)
                    if new_find is None:
                        # Fail only if the either hostsgroups do not exist.
                        ansible_module.fail_json(
                            msg="Attribute `rename` can not be used, unless "
                            "hostgroup exists.")

            elif state == "absent":
                if action == "hostgroup":
                    if res_find is not None:
                        commands.append([name, "hostgroup_del", {}])

                elif action == "member":
                    if res_find is None:
                        ansible_module.fail_json(msg="No hostgroup '%s'" %
                                                 name)

                    # Ensure members are absent
                    commands.append([
                        name, "hostgroup_remove_member", {
                            "host": host,
                            "hostgroup": hostgroup,
                        }
                    ])

                    if has_add_membermanager:
                        # Remove membermanager users and groups
                        if membermanager_user is not None or \
                           membermanager_group is not None:
                            commands.append([
                                name, "hostgroup_remove_member_manager", {
                                    "user": membermanager_user,
                                    "group": membermanager_group,
                                }
                            ])

            else:
                ansible_module.fail_json(msg="Unkown state '%s'" % state)

        # Check mode exit
        if ansible_module.check_mode:
            ansible_module.exit_json(changed=len(commands) > 0, **exit_args)

        # Execute commands
        for name, command, args in commands:
            try:
                result = api_command(ansible_module, command, name, args)
                if "completed" in result:
                    if result["completed"] > 0:
                        changed = True
                else:
                    changed = True
            except Exception as e:
                ansible_module.fail_json(msg="%s: %s: %s" %
                                         (command, name, str(e)))
            # Get all errors
            # All "already a member" and "not a member" failures in the
            # result are ignored. All others are reported.
            errors = []
            for failed_item in result.get("failed", []):
                failed = result["failed"][failed_item]
                for member_type in failed:
                    for member, failure in failed[member_type]:
                        if "already a member" in failure \
                           or "not a member" in failure:
                            continue
                        errors.append("%s: %s %s: %s" %
                                      (command, member_type, member, failure))
            if len(errors) > 0:
                ansible_module.fail_json(msg=", ".join(errors))

    except Exception as e:
        ansible_module.fail_json(msg=str(e))

    finally:
        temp_kdestroy(ccache_dir, ccache_name)

    # Done

    ansible_module.exit_json(changed=changed, **exit_args)
Пример #27
0
def main():
    ansible_module = AnsibleModule(
        argument_spec=dict(
            # general
            ipaadmin_principal=dict(type="str", default="admin"),
            ipaadmin_password=dict(type="str", required=False, no_log=True),
            name=dict(type="list",
                      aliases=["aciname"],
                      default=None,
                      required=True),
            # present
            permission=dict(required=False,
                            type='list',
                            aliases=["permissions"],
                            default=None),
            attribute=dict(required=False,
                           type='list',
                           aliases=["attrs"],
                           default=None),
            membergroup=dict(type="str", aliases=["memberof"], default=None),
            group=dict(type="str", default=None),
            action=dict(type="str",
                        default="delegation",
                        choices=["member", "delegation"]),
            # state
            state=dict(type="str",
                       default="present",
                       choices=["present", "absent"]),
        ),
        supports_check_mode=True,
    )

    ansible_module._ansible_debug = True

    # Get parameters

    # general
    ipaadmin_principal = module_params_get(ansible_module,
                                           "ipaadmin_principal")
    ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password")
    names = module_params_get(ansible_module, "name")

    # present
    permission = module_params_get(ansible_module, "permission")
    attribute = module_params_get(ansible_module, "attribute")
    membergroup = module_params_get(ansible_module, "membergroup")
    group = module_params_get(ansible_module, "group")
    action = module_params_get(ansible_module, "action")
    # state
    state = module_params_get(ansible_module, "state")

    # Check parameters

    if state == "present":
        if len(names) != 1:
            ansible_module.fail_json(
                msg="Only one delegation be added at a time.")
        if action == "member":
            invalid = ["permission", "membergroup", "group"]
            for x in invalid:
                if vars()[x] is not None:
                    ansible_module.fail_json(
                        msg="Argument '%s' can not be used with action "
                        "'%s' and state '%s'" % (x, action, state))

    if state == "absent":
        if len(names) < 1:
            ansible_module.fail_json(msg="No name given.")
        invalid = ["permission", "membergroup", "group"]
        if action == "delegation":
            invalid.append("attribute")
        for x in invalid:
            if vars()[x] is not None:
                ansible_module.fail_json(
                    msg="Argument '%s' can not be used with action "
                    "'%s' and state '%s'" % (x, action, state))

    if permission is not None:
        perm = [p for p in permission if p not in ("read", "write")]
        if perm:
            ansible_module.fail_json(msg="Invalid permission '%s'" % perm)
        if len(set(permission)) != len(permission):
            ansible_module.fail_json(
                msg="Invalid permission '%s', items are not unique" %
                repr(permission))

    if attribute is not None:
        if len(set(attribute)) != len(attribute):
            ansible_module.fail_json(
                msg="Invalid attribute '%s', items are not unique" %
                repr(attribute))

    # Init

    changed = False
    exit_args = {}
    ccache_dir = None
    ccache_name = None
    try:
        if not valid_creds(ansible_module, ipaadmin_principal):
            ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
                                                 ipaadmin_password)
        api_connect()

        commands = []
        for name in names:
            # Make sure delegation exists
            res_find = find_delegation(ansible_module, name)

            # Create command
            if state == "present":

                # Generate args
                args = gen_args(permission, attribute, membergroup, group)

                if action == "delegation":
                    # Found the delegation
                    if res_find is not None:
                        # For all settings is args, check if there are
                        # different settings in the find result.
                        # If yes: modify
                        if not compare_args_ipa(ansible_module, args,
                                                res_find):
                            commands.append([name, "delegation_mod", args])
                    else:
                        commands.append([name, "delegation_add", args])

                elif action == "member":
                    if res_find is None:
                        ansible_module.fail_json(msg="No delegation '%s'" %
                                                 name)

                    if attribute is None:
                        ansible_module.fail_json(msg="No attributes given")

                    # New attribute list (add given ones to find result)
                    # Make list with unique entries
                    attrs = list(set(list(res_find["attrs"]) + attribute))
                    if len(attrs) > len(res_find["attrs"]):
                        commands.append(
                            [name, "delegation_mod", {
                                "attrs": attrs
                            }])

            elif state == "absent":
                if action == "delegation":
                    if res_find is not None:
                        commands.append([name, "delegation_del", {}])

                elif action == "member":
                    if res_find is None:
                        ansible_module.fail_json(msg="No delegation '%s'" %
                                                 name)

                    if attribute is None:
                        ansible_module.fail_json(msg="No attributes given")

                    # New attribute list (remove given ones from find result)
                    # Make list with unique entries
                    attrs = list(set(res_find["attrs"]) - set(attribute))
                    if len(attrs) < 1:
                        ansible_module.fail_json(
                            msg="At minimum one attribute is needed.")

                    # Entries New number of attributes is smaller
                    if len(attrs) < len(res_find["attrs"]):
                        commands.append(
                            [name, "delegation_mod", {
                                "attrs": attrs
                            }])

            else:
                ansible_module.fail_json(msg="Unkown state '%s'" % state)

        # Execute commands

        for name, command, args in commands:
            try:
                result = api_command(ansible_module, command, name, args)
                if "completed" in result:
                    if result["completed"] > 0:
                        changed = True
                else:
                    changed = True
            except Exception as e:
                ansible_module.fail_json(msg="%s: %s: %s" %
                                         (command, name, str(e)))

    except Exception as e:
        ansible_module.fail_json(msg=str(e))

    finally:
        temp_kdestroy(ccache_dir, ccache_name)

    # Done

    ansible_module.exit_json(changed=changed, **exit_args)
Пример #28
0
def main():
    ansible_module = AnsibleModule(
        argument_spec=dict(
            # general
            ipaadmin_principal=dict(type="str", default="admin"),
            ipaadmin_password=dict(type="str", required=False, no_log=True),

            name=dict(type="list", aliases=["cn"],
                      default=None, required=True),
            # present
            location=dict(required=False, type='str',
                          aliases=["ipalocation_location"], default=None),
            service_weight=dict(required=False, type='int',
                                aliases=["ipaserviceweight"], default=None),
            hidden=dict(required=False, type='bool', default=None),
            no_members=dict(required=False, type='bool', default=None),
            # absent
            delete_continue=dict(required=False, type='bool',
                                 aliases=["continue"], default=None),
            ignore_topology_disconnect=dict(required=False, type='bool',
                                            default=None),
            ignore_last_of_role=dict(required=False, type='bool',
                                     default=None),
            force=dict(required=False, type='bool',
                       default=None),
            # state
            state=dict(type="str", default="present",
                       choices=["present", "absent"]),
        ),
        supports_check_mode=True,
    )

    ansible_module._ansible_debug = True

    # Get parameters

    # general
    ipaadmin_principal = module_params_get(ansible_module,
                                           "ipaadmin_principal")
    ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password")
    names = module_params_get(ansible_module, "name")

    # present
    location = module_params_get(ansible_module, "location")
    service_weight = module_params_get(ansible_module, "service_weight")
    # Service weight smaller than 0 leads to resetting service weight
    if service_weight is not None and \
       (service_weight < -1 or service_weight > 65535):
        ansible_module.fail_json(
            msg="service_weight %d is out of range [-1 .. 65535]" %
            service_weight)
    if service_weight == -1:
        service_weight = ""
    hidden = module_params_get(ansible_module, "hidden")
    no_members = module_params_get(ansible_module, "no_members")

    # absent
    delete_continue = module_params_get(ansible_module, "delete_continue")
    ignore_topology_disconnect = module_params_get(
        ansible_module, "ignore_topology_disconnect")
    ignore_last_of_role = module_params_get(ansible_module,
                                            "ignore_last_of_role")
    force = module_params_get(ansible_module, "force")

    # state
    state = module_params_get(ansible_module, "state")

    # Check parameters

    invalid = []

    if state == "present":
        if len(names) != 1:
            ansible_module.fail_json(
                msg="Only one server can be ensured at a time.")
        invalid = ["delete_continue", "ignore_topology_disconnect",
                   "ignore_last_of_role", "force"]

    if state == "absent":
        if len(names) < 1:
            ansible_module.fail_json(msg="No name given.")
        invalid = ["location", "service_weight", "hidden", "no_members"]

    for x in invalid:
        if vars()[x] is not None:
            ansible_module.fail_json(
                msg="Argument '%s' can not be used with state '%s'" %
                (x, state))

    # Init

    changed = False
    exit_args = {}
    ccache_dir = None
    ccache_name = None
    try:
        if not valid_creds(ansible_module, ipaadmin_principal):
            ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
                                                 ipaadmin_password)
        api_connect()

        commands = []
        for name in names:
            # Make sure server exists
            res_find = find_server(ansible_module, name)

            # Generate args
            args = gen_args(location, service_weight, no_members,
                            delete_continue, ignore_topology_disconnect,
                            ignore_last_of_role, force)

            # Create command
            if state == "present":
                # Server not found
                if res_find is None:
                    ansible_module.fail_json(
                        msg="Server '%s' not found" % name)

                # Remove location from args if "" (transformed to None)
                # and "ipalocation_location" not in res_find for idempotency
                if "ipalocation_location" in args and \
                   args["ipalocation_location"] is None and \
                   "ipalocation_location" not in res_find:
                    del args["ipalocation_location"]

                # Remove service weight from args if ""
                # and "ipaserviceweight" not in res_find for idempotency
                if "ipaserviceweight" in args and \
                   args["ipaserviceweight"] == "" and \
                   "ipaserviceweight" not in res_find:
                    del args["ipaserviceweight"]

                # For all settings is args, check if there are
                # different settings in the find result.
                # If yes: modify
                if not compare_args_ipa(ansible_module, args, res_find):
                    commands.append([name, "server_mod", args])

                # hidden handling
                if hidden is not None:
                    res_role_status = server_role_status(ansible_module,
                                                         name)

                    if "status" in res_role_status:
                        # Fail if status is configured, it should be done
                        # only in the installer
                        if res_role_status["status"] == "configured":
                            ansible_module.fail_json(
                                msg="'%s' in configured state, "
                                "unable to change state" % state)

                        if hidden and res_role_status["status"] == "enabled":
                            commands.append([name, "server_state",
                                             {"state": "hidden"}])
                        if not hidden and \
                           res_role_status["status"] == "hidden":
                            commands.append([name, "server_state",
                                             {"state": "enabled"}])

            elif state == "absent":
                if res_find is not None or force:
                    commands.append([name, "server_del", args])
            else:
                ansible_module.fail_json(msg="Unkown state '%s'" % state)

        # Execute commands

        for name, command, args in commands:
            try:
                result = api_command(ansible_module, command, name,
                                     args)
                if "completed" in result:
                    if result["completed"] > 0:
                        changed = True
                else:
                    changed = True
            except Exception as e:
                ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
                                                             str(e)))

    except Exception as e:
        ansible_module.fail_json(msg=str(e))

    finally:
        temp_kdestroy(ccache_dir, ccache_name)

    # Done

    ansible_module.exit_json(changed=changed, **exit_args)
Пример #29
0
def main():
    ansible_module = AnsibleModule(
        argument_spec=dict(
            # generalgroups
            ipaadmin_principal=dict(type="str", default="admin"),
            ipaadmin_password=dict(type="str", required=False, no_log=True),
            name=dict(type="list", aliases=["cn"], default=None,
                      required=True),
            description=dict(required=False, type="str", default=None),
            vault_type=dict(type="str",
                            aliases=["ipavaulttype"],
                            default=None,
                            required=False,
                            choices=["standard", "symmetric", "asymmetric"]),
            vault_public_key=dict(type="str",
                                  required=False,
                                  default=None,
                                  aliases=['ipavaultpublickey', 'public_key']),
            vault_public_key_file=dict(type="str",
                                       required=False,
                                       default=None,
                                       aliases=['public_key_file']),
            vault_private_key=dict(
                type="str",
                required=False,
                default=None,
                no_log=True,
                aliases=['ipavaultprivatekey', 'private_key']),
            vault_private_key_file=dict(type="str",
                                        required=False,
                                        default=None,
                                        aliases=['private_key_file']),
            vault_salt=dict(type="str",
                            required=False,
                            default=None,
                            aliases=['ipavaultsalt', 'salt']),
            username=dict(type="str",
                          required=False,
                          default=None,
                          aliases=['user']),
            service=dict(type="str", required=False, default=None),
            shared=dict(type="bool", required=False, default=None),
            users=dict(required=False, type='list', default=None),
            groups=dict(required=False, type='list', default=None),
            services=dict(required=False, type='list', default=None),
            owners=dict(required=False,
                        type='list',
                        default=None,
                        aliases=['ownerusers']),
            ownergroups=dict(required=False, type='list', default=None),
            ownerservices=dict(required=False, type='list', default=None),
            vault_data=dict(type="str",
                            required=False,
                            default=None,
                            no_log=True,
                            aliases=['ipavaultdata', 'data']),
            datafile_in=dict(type="str",
                             required=False,
                             default=None,
                             aliases=['in']),
            datafile_out=dict(type="str",
                              required=False,
                              default=None,
                              aliases=['out']),
            vault_password=dict(
                type="str",
                required=False,
                default=None,
                no_log=True,
                aliases=['ipavaultpassword', 'password', "old_password"]),
            vault_password_file=dict(
                type="str",
                required=False,
                default=None,
                no_log=False,
                aliases=['password_file', "old_password_file"]),
            new_password=dict(type="str",
                              required=False,
                              default=None,
                              no_log=True),
            new_password_file=dict(type="str",
                                   required=False,
                                   default=None,
                                   no_log=False),
            # state
            action=dict(type="str",
                        default="vault",
                        choices=["vault", "data", "member"]),
            state=dict(type="str",
                       default="present",
                       choices=["present", "absent", "retrieved"]),
        ),
        supports_check_mode=True,
        mutually_exclusive=[['username', 'service', 'shared'],
                            ['datafile_in', 'vault_data'],
                            ['new_password', 'new_password_file'],
                            ['vault_password', 'vault_password_file'],
                            ['vault_public_key', 'vault_public_key_file']],
    )

    ansible_module._ansible_debug = True

    # general
    ipaadmin_principal = module_params_get(ansible_module,
                                           "ipaadmin_principal")
    ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password")
    names = module_params_get(ansible_module, "name")

    # present
    description = module_params_get(ansible_module, "description")

    username = module_params_get(ansible_module, "username")
    service = module_params_get(ansible_module, "service")
    shared = module_params_get(ansible_module, "shared")

    users = module_params_get(ansible_module, "users")
    groups = module_params_get(ansible_module, "groups")
    services = module_params_get(ansible_module, "services")
    owners = module_params_get(ansible_module, "owners")
    ownergroups = module_params_get(ansible_module, "ownergroups")
    ownerservices = module_params_get(ansible_module, "ownerservices")

    vault_type = module_params_get(ansible_module, "vault_type")
    salt = module_params_get(ansible_module, "vault_salt")
    password = module_params_get(ansible_module, "vault_password")
    password_file = module_params_get(ansible_module, "vault_password_file")
    new_password = module_params_get(ansible_module, "new_password")
    new_password_file = module_params_get(ansible_module, "new_password_file")
    public_key = module_params_get(ansible_module, "vault_public_key")
    public_key_file = module_params_get(ansible_module,
                                        "vault_public_key_file")
    private_key = module_params_get(ansible_module, "vault_private_key")
    private_key_file = module_params_get(ansible_module,
                                         "vault_private_key_file")

    vault_data = module_params_get(ansible_module, "vault_data")

    datafile_in = module_params_get(ansible_module, "datafile_in")
    datafile_out = module_params_get(ansible_module, "datafile_out")

    action = module_params_get(ansible_module, "action")
    state = module_params_get(ansible_module, "state")

    # Check parameters

    if state == "present":
        if len(names) != 1:
            ansible_module.fail_json(
                msg="Only one vault can be added at a time.")

    elif state == "absent":
        if len(names) < 1:
            ansible_module.fail_json(msg="No name given.")

    elif state == "retrieved":
        if len(names) != 1:
            ansible_module.fail_json(
                msg="Only one vault can be retrieved at a time.")

    else:
        ansible_module.fail_json(msg="Invalid state '%s'" % state)

    check_parameters(ansible_module, state, action, description, username,
                     service, shared, users, groups, services, owners,
                     ownergroups, ownerservices, vault_type, salt, password,
                     password_file, public_key, public_key_file, private_key,
                     private_key_file, vault_data, datafile_in, datafile_out,
                     new_password, new_password_file)
    # Init

    changed = False
    exit_args = {}
    ccache_dir = None
    ccache_name = None
    try:
        if not valid_creds(ansible_module, ipaadmin_principal):
            ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
                                                 ipaadmin_password)
            # Need to set krb5 ccache name, due to context='ansible-freeipa'
            if ccache_name is not None:
                os.environ["KRB5CCNAME"] = ccache_name

        api_connect(context='ansible-freeipa')

        commands = []

        for name in names:
            # Make sure vault exists
            res_find = find_vault(ansible_module, name, username, service,
                                  shared)

            # Generate args
            args = gen_args(description, username, service, shared, vault_type,
                            salt, password, password_file, public_key,
                            public_key_file, vault_data, datafile_in,
                            datafile_out)
            pwdargs = None

            # Set default vault_type if needed.
            if vault_type is None and vault_data is not None:
                if res_find is not None:
                    res_vault_type = res_find.get('ipavaulttype')[0]
                    args['ipavaulttype'] = vault_type = res_vault_type
                else:
                    args['ipavaulttype'] = vault_type = u"symmetric"

            # Create command
            if state == "present":
                # verify data encription args
                check_encryption_params(
                    ansible_module, state, action, vault_type, salt, password,
                    password_file, public_key, public_key_file, private_key,
                    private_key_file, vault_data, datafile_in, datafile_out,
                    new_password, new_password_file, res_find)

                # Found the vault
                if action == "vault":
                    if res_find is not None:
                        # For all settings is args, check if there are
                        # different settings in the find result.
                        # If yes: modify
                        if not compare_args_ipa(ansible_module, args,
                                                res_find):
                            commands.append([name, "vault_mod_internal", args])

                    else:
                        if vault_type == 'symmetric' \
                           and 'ipavaultsalt' not in args:
                            args['ipavaultsalt'] = os.urandom(32)

                        commands.append([name, "vault_add_internal", args])

                        if vault_type != 'standard' and vault_data is None:
                            vault_data = ''

                        # Set res_find to empty dict for next steps
                        res_find = {}

                    # Generate adittion and removal lists
                    user_add, user_del = \
                        gen_add_del_lists(users,
                                          res_find.get('member_user', []))
                    group_add, group_del = \
                        gen_add_del_lists(groups,
                                          res_find.get('member_group', []))
                    service_add, service_del = \
                        gen_add_del_lists(services,
                                          res_find.get('member_service', []))

                    owner_add, owner_del = \
                        gen_add_del_lists(owners,
                                          res_find.get('owner_user', []))

                    ownergroups_add, ownergroups_del = \
                        gen_add_del_lists(ownergroups,
                                          res_find.get('owner_group', []))

                    ownerservice_add, ownerservice_del = \
                        gen_add_del_lists(ownerservices,
                                          res_find.get('owner_service', []))

                    # Add users and groups
                    user_add_args = gen_member_args(args, user_add, group_add,
                                                    service_add)
                    if user_add_args is not None:
                        commands.append(
                            [name, 'vault_add_member', user_add_args])

                    # Remove users and groups
                    user_del_args = gen_member_args(args, user_del, group_del,
                                                    service_del)
                    if user_del_args is not None:
                        commands.append(
                            [name, 'vault_remove_member', user_del_args])

                    # Add owner users and groups
                    owner_add_args = gen_member_args(args, owner_add,
                                                     ownergroups_add,
                                                     ownerservice_add)
                    if owner_add_args is not None:
                        commands.append(
                            [name, 'vault_add_owner', owner_add_args])

                    # Remove owner users and groups
                    owner_del_args = gen_member_args(args, owner_del,
                                                     ownergroups_del,
                                                     ownerservice_del)
                    if owner_del_args is not None:
                        commands.append(
                            [name, 'vault_remove_owner', owner_del_args])

                elif action in "member":
                    # Add users and groups
                    if any([users, groups, services]):
                        user_args = gen_member_args(args, users, groups,
                                                    services)
                        commands.append([name, 'vault_add_member', user_args])
                    if any([owners, ownergroups, ownerservices]):
                        owner_args = gen_member_args(args, owners, ownergroups,
                                                     ownerservices)
                        commands.append([name, 'vault_add_owner', owner_args])

                pwdargs = data_storage_args(args, vault_data, password,
                                            password_file, private_key,
                                            private_key_file, datafile_in,
                                            datafile_out)
                if any([vault_data, datafile_in]):
                    commands.append([name, "vault_archive", pwdargs])

                cmds = change_password(ansible_module, res_find, password,
                                       password_file, new_password,
                                       new_password_file)
                commands.extend(cmds)

            elif state == "retrieved":
                if res_find is None:
                    ansible_module.fail_json(
                        msg="Vault `%s` not found to retrieve data." % name)

                # verify data encription args
                check_encryption_params(
                    ansible_module, state, action, vault_type, salt, password,
                    password_file, public_key, public_key_file, private_key,
                    private_key_file, vault_data, datafile_in, datafile_out,
                    new_password, new_password_file, res_find)

                pwdargs = data_storage_args(args, vault_data, password,
                                            password_file, private_key,
                                            private_key_file, datafile_in,
                                            datafile_out)
                if 'data' in pwdargs:
                    del pwdargs['data']

                commands.append([name, "vault_retrieve", pwdargs])

            elif state == "absent":
                if 'ipavaulttype' in args:
                    del args['ipavaulttype']

                if action == "vault":
                    if res_find is not None:
                        commands.append([name, "vault_del", args])

                elif action == "member":
                    # remove users and groups
                    if any([users, groups, services]):
                        user_args = gen_member_args(args, users, groups,
                                                    services)
                        commands.append(
                            [name, 'vault_remove_member', user_args])

                    if any([owners, ownergroups, ownerservices]):
                        owner_args = gen_member_args(args, owners, ownergroups,
                                                     ownerservices)
                        commands.append(
                            [name, 'vault_remove_owner', owner_args])
                else:
                    ansible_module.fail_json(
                        msg="Invalid action '%s' for state '%s'" %
                        (action, state))
            else:
                ansible_module.fail_json(msg="Unknown state '%s'" % state)

        # Execute commands

        errors = []
        for name, command, args in commands:
            try:
                result = api_command(ansible_module, command, name, args)

                if command == 'vault_archive':
                    changed = 'Archived data into' in result['summary']
                elif command == 'vault_retrieve':
                    if 'result' not in result:
                        raise Exception("No result obtained.")
                    if "data" in result["result"]:
                        data_return = exit_args.setdefault("vault", {})
                        data_return["data"] = result["result"]["data"]
                    else:
                        if not datafile_out:
                            raise Exception("No data retrieved.")
                    changed = False
                else:
                    if "completed" in result:
                        if result["completed"] > 0:
                            changed = True
                    else:
                        changed = True
            except EmptyModlist:
                result = {}
            except Exception as exception:
                ansible_module.fail_json(msg="%s: %s: %s" %
                                         (command, name, str(exception)))

            # Get all errors
            # All "already a member" and "not a member" failures in the
            # result are ignored. All others are reported.
            if "failed" in result and len(result["failed"]) > 0:
                for item in result["failed"]:
                    failed_item = result["failed"][item]
                    for member_type in failed_item:
                        for member, failure in failed_item[member_type]:
                            if "already a member" in failure \
                               or "not a member" in failure:
                                continue
                            errors.append(
                                "%s: %s %s: %s" %
                                (command, member_type, member, failure))
        if len(errors) > 0:
            ansible_module.fail_json(msg=", ".join(errors))

    except Exception as exception:
        ansible_module.fail_json(msg=str(exception))

    finally:
        temp_kdestroy(ccache_dir, ccache_name)

    # Done
    ansible_module.exit_json(changed=changed, **exit_args)
Пример #30
0
def main():
    ansible_module = AnsibleModule(
        argument_spec=dict(
            # general
            ipaadmin_principal=dict(type="str", default="admin"),
            ipaadmin_password=dict(type="str", required=False, no_log=True),
            name=dict(type="list",
                      aliases=["cn", "service"],
                      default=None,
                      required=True),
            # present
            description=dict(type="str", default=None),

            # state
            state=dict(type="str",
                       default="present",
                       choices=["present", "absent"]),
        ),
        supports_check_mode=True,
    )

    ansible_module._ansible_debug = True

    # Get parameters

    # general
    ipaadmin_principal = ansible_module.params.get("ipaadmin_principal")
    ipaadmin_password = ansible_module.params.get("ipaadmin_password")
    names = ansible_module.params.get("name")

    # present
    description = ansible_module.params.get("description")

    # state
    state = ansible_module.params.get("state")

    # Check parameters

    if state == "present":
        if len(names) != 1:
            ansible_module.fail_json(
                msg="Only one hbacsvc can be set at a time.")

    if state == "absent":
        if len(names) < 1:
            ansible_module.fail_json(msg="No name given.")
        invalid = ["description"]
        for x in invalid:
            if vars()[x] is not None:
                ansible_module.fail_json(
                    msg="Argument '%s' can not be used with state '%s'" %
                    (x, state))

    # Init

    changed = False
    exit_args = {}
    ccache_dir = None
    ccache_name = None
    try:
        if not valid_creds(ansible_module, ipaadmin_principal):
            ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
                                                 ipaadmin_password)
        api_connect()

        commands = []

        for name in names:
            # Try to find hbacsvc
            res_find = find_hbacsvc(ansible_module, name)

            # Create command
            if state == "present":
                # Generate args
                args = gen_args(description)

                # Found the hbacsvc
                if res_find is not None:
                    # For all settings is args, check if there are
                    # different settings in the find result.
                    # If yes: modify
                    if not compare_args_ipa(ansible_module, args, res_find):
                        commands.append([name, "hbacsvc_mod", args])
                else:
                    commands.append([name, "hbacsvc_add", args])

            elif state == "absent":
                if res_find is not None:
                    commands.append([name, "hbacsvc_del", {}])

            else:
                ansible_module.fail_json(msg="Unkown state '%s'" % state)

        # Execute commands

        for name, command, args in commands:
            try:
                api_command(ansible_module, command, to_text(name), args)
                changed = True
            except Exception as e:
                ansible_module.fail_json(msg="%s: %s: %s" %
                                         (command, name, str(e)))

    except Exception as e:
        ansible_module.fail_json(msg=str(e))

    finally:
        temp_kdestroy(ccache_dir, ccache_name)

    # Done

    ansible_module.exit_json(changed=changed, **exit_args)