예제 #1
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)
예제 #2
0
def main():
    ansible_module = init_ansible_module()

    # 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")

    # service attributes
    principal = module_params_get(ansible_module, "principal")
    certificate = module_params_get(ansible_module, "certificate")
    pac_type = module_params_get(ansible_module, "pac_type")
    auth_ind = module_params_get(ansible_module, "auth_ind")
    skip_host_check = module_params_get(ansible_module, "skip_host_check")
    force = module_params_get(ansible_module, "force")
    requires_pre_auth = module_params_get(ansible_module, "requires_pre_auth")
    ok_as_delegate = module_params_get(ansible_module, "ok_as_delegate")
    ok_to_auth_as_delegate = module_params_get(ansible_module,
                                               "ok_to_auth_as_delegate")

    smb = module_params_get(ansible_module, "smb")
    netbiosname = module_params_get(ansible_module, "netbiosname")

    host = module_params_get(ansible_module, "host")

    allow_create_keytab_user = module_params_get(ansible_module,
                                                 "allow_create_keytab_user")
    allow_create_keytab_group = module_params_get(ansible_module,
                                                  "allow_create_keytab_group")
    allow_create_keytab_host = module_params_get(ansible_module,
                                                 "allow_create_keytab_host")
    allow_create_keytab_hostgroup = module_params_get(
        ansible_module, "allow_create_keytab_hostgroup")

    allow_retrieve_keytab_user = module_params_get(
        ansible_module, "allow_retrieve_keytab_user")
    allow_retrieve_keytab_group = module_params_get(
        ansible_module, "allow_retrieve_keytab_group")
    allow_retrieve_keytab_host = module_params_get(
        ansible_module, "allow_retrieve_keytab_host")
    allow_retrieve_keytab_hostgroup = module_params_get(
        ansible_module, "allow_retrieve_keytab_hostgroup")
    delete_continue = module_params_get(ansible_module, "delete_continue")

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

    # check parameters
    check_parameters(ansible_module, state, action, names, vars())

    # 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_skip_host_check = api_check_param("service_add", "skip_host_check")
        if skip_host_check and not has_skip_host_check:
            ansible_module.fail_json(
                msg="Skipping host check is not supported by your IPA version")

        commands = []

        for name in names:
            res_find = find_service(ansible_module, name, netbiosname)

            if state == "present":
                # if service exists, 'smb' cannot be used.

                if action == "service":
                    args = gen_args(pac_type, auth_ind, skip_host_check, force,
                                    requires_pre_auth, ok_as_delegate,
                                    ok_to_auth_as_delegate)
                    if not has_skip_host_check and 'skip_host_check' in args:
                        del args['skip_host_check']

                    if res_find is None:
                        if smb:
                            if netbiosname is not None:
                                args['ipantflatname'] = netbiosname
                            commands.append([name, 'service_add_smb', args])
                        else:
                            commands.append([name, 'service_add', args])

                        certificate_add = certificate or []
                        certificate_del = []
                        host_add = host or []
                        host_del = []
                        principal_add = principal or []
                        principal_del = []
                        allow_create_keytab_user_add = \
                            allow_create_keytab_user or []
                        allow_create_keytab_user_del = []
                        allow_create_keytab_group_add = \
                            allow_create_keytab_group or []
                        allow_create_keytab_group_del = []
                        allow_create_keytab_host_add = \
                            allow_create_keytab_host or []
                        allow_create_keytab_host_del = []
                        allow_create_keytab_hostgroup_add = \
                            allow_create_keytab_hostgroup or []
                        allow_create_keytab_hostgroup_del = []
                        allow_retrieve_keytab_user_add = \
                            allow_retrieve_keytab_user or []
                        allow_retrieve_keytab_user_del = []
                        allow_retrieve_keytab_group_add = \
                            allow_retrieve_keytab_group or []
                        allow_retrieve_keytab_group_del = []
                        allow_retrieve_keytab_host_add = \
                            allow_retrieve_keytab_host or []
                        allow_retrieve_keytab_host_del = []
                        allow_retrieve_keytab_hostgroup_add = \
                            allow_retrieve_keytab_hostgroup or []
                        allow_retrieve_keytab_hostgroup_del = []

                    else:
                        for remove in ['skip_host_check', 'force']:
                            if remove in args:
                                del args[remove]

                        if not compare_args_ipa(ansible_module, args,
                                                res_find):
                            commands.append([name, "service_mod", args])

                        certificate_add, certificate_del = gen_add_del_lists(
                            certificate, res_find.get("usercertificate"))

                        host_add, host_del = gen_add_del_lists(
                            host, res_find.get('managedby_host', []))

                        principal_add, principal_del = gen_add_del_lists(
                            principal, res_find.get("principal"))

                        (allow_create_keytab_user_add,
                         allow_create_keytab_user_del) = \
                            gen_add_del_lists(
                                allow_create_keytab_user, res_find.get(
                                    'ipaallowedtoperform_write_keys_user',
                                    []))
                        (allow_retrieve_keytab_user_add,
                         allow_retrieve_keytab_user_del) = \
                            gen_add_del_lists(
                                allow_retrieve_keytab_user, res_find.get(
                                    'ipaallowedtoperform_read_keys_user',
                                    []))
                        (allow_create_keytab_group_add,
                         allow_create_keytab_group_del) = \
                            gen_add_del_lists(
                                allow_create_keytab_group, res_find.get(
                                    'ipaallowedtoperform_write_keys_group',
                                    []))
                        (allow_retrieve_keytab_group_add,
                         allow_retrieve_keytab_group_del) = \
                            gen_add_del_lists(
                                allow_retrieve_keytab_group,
                                res_find.get(
                                    'ipaallowedtoperform_read_keys_group',
                                    []))
                        (allow_create_keytab_host_add,
                         allow_create_keytab_host_del) = \
                            gen_add_del_lists(
                                allow_create_keytab_host,
                                res_find.get(
                                    'ipaallowedtoperform_write_keys_host',
                                    []))
                        (allow_retrieve_keytab_host_add,
                         allow_retrieve_keytab_host_del) = \
                            gen_add_del_lists(
                                allow_retrieve_keytab_host,
                                res_find.get(
                                    'ipaallowedtoperform_read_keys_host',
                                    []))
                        (allow_create_keytab_hostgroup_add,
                         allow_create_keytab_hostgroup_del) = \
                            gen_add_del_lists(
                                allow_create_keytab_hostgroup,
                                res_find.get(
                                    'ipaallowedtoperform_write_keys_hostgroup',
                                    []))
                        (allow_retrieve_keytab_hostgroup_add,
                         allow_retrieve_keytab_hostgroup_del) = \
                            gen_add_del_lists(
                                allow_retrieve_keytab_hostgroup,
                                res_find.get(
                                    'ipaallowedtoperform_read_keys_hostgroup',
                                    []))

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

                    existing = res_find.get('usercertificate', [])
                    if certificate is None:
                        certificate_add = []
                    else:
                        certificate_add = [
                            c for c in certificate if c not in existing
                        ]
                    certificate_del = []
                    host_add = host or []
                    host_del = []
                    principal_add = principal or []
                    principal_del = []

                    allow_create_keytab_user_add = \
                        allow_create_keytab_user or []
                    allow_create_keytab_user_del = []
                    allow_create_keytab_group_add = \
                        allow_create_keytab_group or []
                    allow_create_keytab_group_del = []
                    allow_create_keytab_host_add = \
                        allow_create_keytab_host or []
                    allow_create_keytab_host_del = []
                    allow_create_keytab_hostgroup_add = \
                        allow_create_keytab_hostgroup or []
                    allow_create_keytab_hostgroup_del = []
                    allow_retrieve_keytab_user_add = \
                        allow_retrieve_keytab_user or []
                    allow_retrieve_keytab_user_del = []
                    allow_retrieve_keytab_group_add = \
                        allow_retrieve_keytab_group or []
                    allow_retrieve_keytab_group_del = []
                    allow_retrieve_keytab_host_add = \
                        allow_retrieve_keytab_host or []
                    allow_retrieve_keytab_host_del = []
                    allow_retrieve_keytab_hostgroup_add = \
                        allow_retrieve_keytab_hostgroup or []
                    allow_retrieve_keytab_hostgroup_del = []

                # Add principals
                for _principal in principal_add:
                    commands.append([
                        name, "service_add_principal", {
                            "krbprincipalname": _principal,
                        }
                    ])

                # Remove principals
                for _principal in principal_del:
                    commands.append([
                        name, "service_remove_principal", {
                            "krbprincipalname": _principal,
                        }
                    ])

                for _certificate in certificate_add:
                    commands.append([
                        name, "service_add_cert", {
                            "usercertificate": _certificate,
                        }
                    ])
                # Remove certificates
                for _certificate in certificate_del:
                    commands.append([
                        name, "service_remove_cert", {
                            "usercertificate": _certificate,
                        }
                    ])

                # Add hosts.
                if host is not None and len(host) > 0 and len(host_add) > 0:
                    commands.append(
                        [name, "service_add_host", {
                            "host": host_add
                        }])
                # Remove hosts
                if host is not None and len(host) > 0 and len(host_del) > 0:
                    commands.append(
                        [name, "service_remove_host", {
                            "host": host_del
                        }])

                # Allow create keytab
                if len(allow_create_keytab_user_add) > 0 or \
                   len(allow_create_keytab_group_add) > 0 or \
                   len(allow_create_keytab_host_add) > 0 or \
                   len(allow_create_keytab_hostgroup_add) > 0:
                    commands.append([
                        name, "service_allow_create_keytab", {
                            'user': allow_create_keytab_user_add,
                            'group': allow_create_keytab_group_add,
                            'host': allow_create_keytab_host_add,
                            'hostgroup': allow_create_keytab_hostgroup_add
                        }
                    ])

                # Disallow create keytab
                if len(allow_create_keytab_user_del) > 0 or \
                   len(allow_create_keytab_group_del) > 0 or \
                   len(allow_create_keytab_host_del) > 0 or \
                   len(allow_create_keytab_hostgroup_del) > 0:
                    commands.append([
                        name, "service_disallow_create_keytab", {
                            'user': allow_create_keytab_user_del,
                            'group': allow_create_keytab_group_del,
                            'host': allow_create_keytab_host_del,
                            'hostgroup': allow_create_keytab_hostgroup_del
                        }
                    ])

                # Allow retrieve keytab
                if len(allow_retrieve_keytab_user_add) > 0 or \
                   len(allow_retrieve_keytab_group_add) > 0 or \
                   len(allow_retrieve_keytab_host_add) > 0 or \
                   len(allow_retrieve_keytab_hostgroup_add) > 0:
                    commands.append([
                        name, "service_allow_retrieve_keytab", {
                            'user': allow_retrieve_keytab_user_add,
                            'group': allow_retrieve_keytab_group_add,
                            'host': allow_retrieve_keytab_host_add,
                            'hostgroup': allow_retrieve_keytab_hostgroup_add
                        }
                    ])

                # Disllow retrieve keytab
                if len(allow_retrieve_keytab_user_del) > 0 or \
                   len(allow_retrieve_keytab_group_del) > 0 or \
                   len(allow_retrieve_keytab_host_del) > 0 or \
                   len(allow_retrieve_keytab_hostgroup_del) > 0:
                    commands.append([
                        name, "service_disallow_retrieve_keytab", {
                            'user': allow_retrieve_keytab_user_del,
                            'group': allow_retrieve_keytab_group_del,
                            'host': allow_retrieve_keytab_host_del,
                            'hostgroup': allow_retrieve_keytab_hostgroup_del
                        }
                    ])

            elif state == "absent":
                if action == "service":
                    if res_find is not None:
                        args = {'continue': True if delete_continue else False}
                        commands.append([name, 'service_del', args])

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

                    # Remove principals
                    if principal is not None:
                        for _principal in principal:
                            commands.append([
                                name, "service_remove_principal", {
                                    "krbprincipalname": _principal,
                                }
                            ])
                    # Remove certificates
                    if certificate is not None:
                        existing = res_find.get('usercertificate', [])
                        for _certificate in certificate:
                            if _certificate in existing:
                                commands.append([
                                    name, "service_remove_cert", {
                                        "usercertificate": _certificate,
                                    }
                                ])

                    # Add hosts
                    if host is not None:
                        commands.append(
                            [name, "service_remove_host", {
                                "host": host
                            }])

                    # Allow create keytab
                    if allow_create_keytab_user is not None or \
                       allow_create_keytab_group is not None or \
                       allow_create_keytab_host is not None or \
                       allow_create_keytab_hostgroup is not None:
                        commands.append([
                            name, "service_disallow_create_keytab", {
                                'user': allow_create_keytab_user,
                                'group': allow_create_keytab_group,
                                'host': allow_create_keytab_host,
                                'hostgroup': allow_create_keytab_hostgroup
                            }
                        ])

                    # Allow retriev keytab
                    if allow_retrieve_keytab_user is not None or \
                       allow_retrieve_keytab_group is not None or \
                       allow_retrieve_keytab_host is not None or \
                       allow_retrieve_keytab_hostgroup is not None:
                        commands.append([
                            name, "service_disallow_retrieve_keytab", {
                                'user': allow_retrieve_keytab_user,
                                'group': allow_retrieve_keytab_group,
                                'host': allow_retrieve_keytab_host,
                                'hostgroup': allow_retrieve_keytab_hostgroup
                            }
                        ])

            elif state == "disabled":
                if action == "service":
                    if res_find is not None:
                        has_cert = bool(res_find.get('usercertificate'))
                        has_keytab = res_find.get('has_keytab', False)
                        if has_cert or has_keytab:
                            commands.append([name, 'service_disable', {}])
                else:
                    ansible_module.fail_json(
                        msg="Invalid action '%s' for state '%s'" %
                        (action, state))
            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
        errors = []
        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 ex:
                ansible_module.fail_json(msg="%s: %s: %s" %
                                         (command, name, str(ex)))
            # 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 ex:
        ansible_module.fail_json(msg=str(ex))

    finally:
        temp_kdestroy(ccache_dir, ccache_name)

    # Done
    ansible_module.exit_json(changed=changed, **exit_args)
예제 #3
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),
            gid=dict(type="int", aliases=["gidnumber"], default=None),
            nonposix=dict(required=False, type='bool', default=None),
            external=dict(required=False, type='bool', default=None),
            nomembers=dict(required=False, type='bool', default=None),
            user=dict(required=False, type='list', default=None),
            group=dict(required=False, type='list', default=None),
            service=dict(required=False, type='list', default=None),
            action=dict(type="str",
                        default="group",
                        choices=["member", "group"]),
            # 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
    description = module_params_get(ansible_module, "description")
    gid = module_params_get(ansible_module, "gid")
    nonposix = module_params_get(ansible_module, "nonposix")
    external = module_params_get(ansible_module, "external")
    nomembers = module_params_get(ansible_module, "nomembers")
    user = module_params_get(ansible_module, "user")
    group = module_params_get(ansible_module, "group")
    service = module_params_get(ansible_module, "service")
    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 group can be added at a time.")
        if action == "member":
            invalid = [
                "description", "gid", "nonposix", "external", "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 == "absent":
        if len(names) < 1:
            ansible_module.fail_json(msg="No name given.")
        invalid = ["description", "gid", "nonposix", "external", "nomembers"]
        if action == "group":
            invalid.extend(["user", "group", "service"])
        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_member_service = api_check_param("group_add_member", "service")
        if service is not None and not has_add_member_service:
            ansible_module.fail_json(
                msg="Managing a service as part of a group is not supported "
                "by your IPA version")

        commands = []

        for name in names:
            # Make sure group exists
            res_find = find_group(ansible_module, name)

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

                if action == "group":
                    # Found the group
                    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, "group_mod", args])
                    else:
                        commands.append([name, "group_add", args])
                        # Set res_find to empty dict for next step
                        res_find = {}

                    member_args = gen_member_args(user, group, service)
                    if not compare_args_ipa(ansible_module, member_args,
                                            res_find):
                        # Generate addition and removal lists
                        user_add = list(
                            set(user or []) -
                            set(res_find.get("member_user", [])))
                        user_del = list(
                            set(res_find.get("member_user", [])) -
                            set(user or []))
                        group_add = list(
                            set(group or []) -
                            set(res_find.get("member_group", [])))
                        group_del = list(
                            set(res_find.get("member_group", [])) -
                            set(group or []))
                        service_add = list(
                            set(service or []) -
                            set(res_find.get("member_service", [])))
                        service_del = list(
                            set(res_find.get("member_service", [])) -
                            set(service or []))

                        if has_add_member_service:
                            # Add members
                            if len(user_add) > 0 or len(group_add) > 0 or \
                               len(service_add) > 0:
                                commands.append([
                                    name, "group_add_member", {
                                        "user": user_add,
                                        "group": group_add,
                                        "service": service_add,
                                    }
                                ])
                            # Remove members
                            if len(user_del) > 0 or len(group_del) > 0 or \
                               len(service_del) > 0:
                                commands.append([
                                    name, "group_remove_member", {
                                        "user": user_del,
                                        "group": group_del,
                                        "service": service_del,
                                    }
                                ])
                        else:
                            # Add members
                            if len(user_add) > 0 or len(group_add) > 0:
                                commands.append([
                                    name, "group_add_member", {
                                        "user": user_add,
                                        "group": group_add,
                                    }
                                ])
                            # Remove members
                            if len(user_del) > 0 or len(group_del) > 0:
                                commands.append([
                                    name, "group_remove_member", {
                                        "user": user_del,
                                        "group": group_del,
                                    }
                                ])
                elif action == "member":
                    if res_find is None:
                        ansible_module.fail_json(msg="No group '%s'" % name)
                    if has_add_member_service:
                        commands.append([
                            name, "group_add_member", {
                                "user": user,
                                "group": group,
                                "service": service,
                            }
                        ])
                    else:
                        commands.append([
                            name, "group_add_member", {
                                "user": user,
                                "group": group,
                            }
                        ])

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

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

                    commands.append([
                        name, "group_remove_member", {
                            "user": user,
                            "group": group,
                            "service": service,
                        }
                    ])
            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)))
            # Get all errors
            # All "already a member" and "not a member" failures in the
            # result are ignored. All others are reported.
            errors = []
            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 e:
        ansible_module.fail_json(msg=str(e))

    finally:
        temp_kdestroy(ccache_dir, ccache_name)

    # Done

    ansible_module.exit_json(changed=changed, **exit_args)
예제 #4
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),
            gid=dict(type="int", aliases=["gidnumber"], default=None),
            nonposix=dict(required=False, type='bool', default=None),
            external=dict(required=False, type='bool', default=None),
            posix=dict(required=False, type='bool', default=None),
            nomembers=dict(required=False, type='bool', default=None),
            user=dict(required=False, type='list', default=None),
            group=dict(required=False, type='list', default=None),
            service=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),
            externalmember=dict(
                required=False,
                type='list',
                default=None,
                aliases=["ipaexternalmember", "external_member"]),
            action=dict(type="str",
                        default="group",
                        choices=["member", "group"]),
            # state
            state=dict(type="str",
                       default="present",
                       choices=["present", "absent"]),
        ),
        mutually_exclusive=[['posix', 'nonposix']],
        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")
    gid = module_params_get(ansible_module, "gid")
    nonposix = module_params_get(ansible_module, "nonposix")
    external = module_params_get(ansible_module, "external")
    posix = module_params_get(ansible_module, "posix")
    nomembers = module_params_get(ansible_module, "nomembers")
    user = module_params_get(ansible_module, "user")
    group = module_params_get(ansible_module, "group")
    service = module_params_get(ansible_module, "service")
    membermanager_user = module_params_get(ansible_module,
                                           "membermanager_user")
    membermanager_group = module_params_get(ansible_module,
                                            "membermanager_group")
    externalmember = module_params_get(ansible_module, "externalmember")
    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 group can be added at a time.")
        if action == "member":
            invalid = [
                "description", "gid", "posix", "nonposix", "external",
                "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 == "absent":
        if len(names) < 1:
            ansible_module.fail_json(msg="No name given.")
        invalid = [
            "description", "gid", "posix", "nonposix", "external", "nomembers"
        ]
        if action == "group":
            invalid.extend(["user", "group", "service", "externalmember"])
        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_member_service = api_check_param("group_add_member", "service")
        if service is not None and not has_add_member_service:
            ansible_module.fail_json(
                msg="Managing a service as part of a group is not supported "
                "by your IPA version")

        has_add_membermanager = api_check_command("group_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")

        commands = []

        for name in names:
            # Make sure group exists
            res_find = find_group(ansible_module, name)

            # Create command
            if state == "present":
                # Can't change an existing posix group
                check_objectclass_args(ansible_module, res_find, nonposix,
                                       posix, external)

                # Generate args
                args = gen_args(description, gid, nomembers)

                if action == "group":
                    # Found the group
                    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 should_modify_group(ansible_module, res_find, args,
                                               nonposix, posix, external):
                            if (posix or
                                (nonposix is not None and not nonposix)):
                                args['posix'] = True
                            if external:
                                args['external'] = True
                            commands.append([name, "group_mod", args])
                    else:
                        if nonposix or (posix is not None and not posix):
                            args['nonposix'] = True
                        if external:
                            args['external'] = True
                        commands.append([name, "group_add", args])
                        # Set res_find dict for next step
                        res_find = {}

                    # if we just created/modified the group, update res_find
                    res_find.setdefault("objectclass", [])
                    if external and not is_external_group(res_find):
                        res_find["objectclass"].append("ipaexternalgroup")
                    if posix and not is_posix_group(res_find):
                        res_find["objectclass"].append("posixgroup")

                    member_args = gen_member_args(user, group, service,
                                                  externalmember)
                    if not compare_args_ipa(ansible_module, member_args,
                                            res_find):
                        # Generate addition and removal lists
                        user_add, user_del = gen_add_del_lists(
                            user, res_find.get("member_user"))

                        group_add, group_del = gen_add_del_lists(
                            group, res_find.get("member_group"))

                        service_add, service_del = gen_add_del_lists(
                            service, res_find.get("member_service"))

                        (externalmember_add,
                         externalmember_del) = gen_add_del_lists(
                             externalmember, res_find.get("member_external"))

                        # setup member args for add/remove members.
                        add_member_args = {
                            "user": user_add,
                            "group": group_add,
                        }
                        del_member_args = {
                            "user": user_del,
                            "group": group_del,
                        }
                        if has_add_member_service:
                            add_member_args["service"] = service_add
                            del_member_args["service"] = service_del

                        if is_external_group(res_find):
                            add_member_args["ipaexternalmember"] = \
                                externalmember_add
                            del_member_args["ipaexternalmember"] = \
                                externalmember_del
                        elif externalmember or external:
                            ansible_module.fail_json(
                                msg="Cannot add external members to a "
                                "non-external group.")

                        # Add members
                        add_members = any([
                            user_add, group_add, service_add,
                            externalmember_add
                        ])
                        if add_members:
                            commands.append(
                                [name, "group_add_member", add_member_args])
                        # Remove members
                        remove_members = any([
                            user_del, group_del, service_del,
                            externalmember_del
                        ])
                        if remove_members:
                            commands.append(
                                [name, "group_remove_member", del_member_args])

                    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, "group_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, "group_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 group '%s'" % name)

                    add_member_args = {
                        "user": user,
                        "group": group,
                    }
                    if has_add_member_service:
                        add_member_args["service"] = service
                    if is_external_group(res_find):
                        add_member_args["ipaexternalmember"] = externalmember
                    elif externalmember:
                        ansible_module.fail_json(
                            msg="Cannot add external members to a "
                            "non-external group.")

                    if any([user, group, service, externalmember]):
                        commands.append(
                            [name, "group_add_member", add_member_args])

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

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

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

                    del_member_args = {
                        "user": user,
                        "group": group,
                    }
                    if has_add_member_service:
                        del_member_args["service"] = service
                    if is_external_group(res_find):
                        del_member_args["ipaexternalmember"] = externalmember
                    elif externalmember:
                        ansible_module.fail_json(
                            msg="Cannot add external members to a "
                            "non-external group.")

                    if any([user, group, service, externalmember]):
                        commands.append(
                            [name, "group_remove_member", del_member_args])

                    if has_add_membermanager:
                        # Remove membermanager users and groups
                        if membermanager_user is not None or \
                           membermanager_group is not None:
                            commands.append([
                                name, "group_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)