Example #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
Example #2
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
Example #3
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
Example #4
0
def main():
    ansible_module = init_ansible_module()

    # Get parameters

    # general
    names = ansible_module.params_get("name")

    # service attributes
    principal = ansible_module.params_get("principal")
    certificate = ansible_module.params_get("certificate")
    pac_type = ansible_module.params_get("pac_type", allow_empty_string=True)
    auth_ind = ansible_module.params_get("auth_ind", allow_empty_string=True)
    skip_host_check = ansible_module.params_get("skip_host_check")
    force = ansible_module.params_get("force")
    requires_pre_auth = ansible_module.params_get("requires_pre_auth")
    ok_as_delegate = ansible_module.params_get("ok_as_delegate")
    ok_to_auth_as_delegate = ansible_module.params_get(
        "ok_to_auth_as_delegate")

    smb = ansible_module.params_get("smb")
    netbiosname = ansible_module.params_get("netbiosname")

    host = ansible_module.params_get("host")

    delete_continue = ansible_module.params_get("delete_continue")

    # action
    action = ansible_module.params_get("action")
    # state
    state = ansible_module.params_get("state")

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

    # Init

    changed = False
    exit_args = {}

    # Connect to IPA API
    with ansible_module.ipa_connect():

        has_skip_host_check = ansible_module.ipa_command_param_exists(
            "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 = []
        keytab_members = ["user", "group", "host", "hostgroup"]

        for name in names:
            res_find = find_service(ansible_module, name)
            res_principals = []

            keytab = {
                "retrieve": {
                    "allow": {k: []
                              for k in keytab_members},
                    "disallow": {k: []
                                 for k in keytab_members},
                },
                "create": {
                    "allow": {k: []
                              for k in keytab_members},
                    "disallow": {k: []
                                 for k in keytab_members},
                },
            }
            certificate_add, certificate_del = [], []
            host_add, host_del = [], []
            principal_add, principal_del = [], []

            if principal and res_find:
                # When comparing principals to the existing ones,
                # the REALM is needded, and are added here for those
                # that do not have it.
                principal = [
                    p if "@" in p else "%s@%s" % (p, api_get_realm())
                    for p in principal
                ]
                principal = list(set(principal))

                # Create list of existing principal aliases as strings
                # to compare with provided ones.
                canonicalname = {
                    to_text(p)
                    for p in res_find.get("krbcanonicalname", [])
                }
                res_principals = [
                    to_text(elem)
                    for elem in res_find.get("krbprincipalname", [])
                ]
                res_principals = list(set(res_principals) - canonicalname)

            if state == "present":
                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 smb:
                        if res_find is None:
                            _name = "cifs/" + name
                            res_find = find_service(ansible_module, _name)
                            if res_find is None:
                                _args = gen_args_smb(netbiosname,
                                                     ok_as_delegate,
                                                     ok_to_auth_as_delegate)
                                commands.append(
                                    [name, 'service_add_smb', _args])
                                res_find = {}
                            # service_add_smb will prefix 'name' with
                            # "cifs/", so we will need to change it here,
                            # so that service_mod, if called later, works.
                            name = _name

                    if res_find is None:
                        commands.append([name, 'service_add', args])
                        # Use an empty res_find to manage members
                        res_find = {}

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

                        if ("ipakrbauthzdata" in args and
                            (args.get("ipakrbauthzdata", [""]) == res_find.get(
                                "ipakrbauthzdata", [""]))):
                            del args["ipakrbauthzdata"]

                        if ("krbprincipalauthind" in args and
                            (args.get("krbprincipalauthind", [""])
                             == res_find.get("krbprincipalauthind", [""]))):
                            del args["krbprincipalauthind"]

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

                    # Manage members
                    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_principals)

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

                    certificate_add = gen_add_list(
                        certificate, res_find.get("usercertificate"))

                    host_add = gen_add_list(host,
                                            res_find.get('managedby_host'))

                    principal_add = gen_add_list(principal, res_principals)

                # get keytab management lists for any 'action'.
                for perm in ["create", "retrieve"]:
                    oper = "write" if perm == "create" else "read"
                    for key in ["user", "group", "host", "hostgroup"]:
                        add_list, del_list = (gen_add_del_lists(
                            ansible_module.params_get("allow_%s_keytab_%s" %
                                                      (perm, key)),
                            res_find.get('ipaallowedtoperform_%s_keys_%s' %
                                         (oper, key))))
                        keytab[perm]["allow"][key] = add_list
                        # Only remove members if action is 'service'
                        if action == "service":
                            keytab[perm]["disallow"][key] = del_list

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

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

                    principal_del = gen_intersection_list(
                        principal, res_principals)

                    certificate_del = gen_intersection_list(
                        certificate, res_find.get("usercertificate"))

                    host_del = gen_intersection_list(
                        host, res_find.get("managedby_host"))

                    for perm in ["create", "retrieve"]:
                        oper = "write" if perm == "create" else "read"
                        for key in ["user", "group", "host", "hostgroup"]:
                            res_param = ('ipaallowedtoperform_%s_keys_%s' %
                                         (oper, key))
                            module_params = ansible_module.params_get(
                                "allow_%s_keytab_%s" % (perm, key))
                            existing = res_find.get(res_param)
                            del_list = (gen_intersection_list(
                                module_params, existing))
                            keytab[perm]["disallow"][key] = del_list

            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))
                # Members are not managed when disabling service.
                # Continue with next 'name'.
                continue
            else:
                ansible_module.fail_json(msg="Unkown state '%s'" % state)

            # Manage members
            if principal_add:
                commands.append([
                    name, "service_add_principal", {
                        "krbprincipalname": principal_add
                    }
                ])
            if principal_del:
                commands.append([
                    name, "service_remove_principal", {
                        "krbprincipalname": principal_del
                    }
                ])

            if certificate_add:
                commands.append([
                    name, "service_add_cert", {
                        "usercertificate": certificate_add
                    }
                ])
            if certificate_del:
                commands.append([
                    name, "service_remove_cert", {
                        "usercertificate": certificate_del
                    }
                ])

            if host_add:
                commands.append([name, "service_add_host", {"host": host_add}])
            if host_del:
                commands.append(
                    [name, "service_remove_host", {
                        "host": host_del
                    }])

            # manage keytab permissions.
            for perm in ["create", "retrieve"]:
                for mode in ["allow", "disallow"]:
                    for key in ["user", "group", "host", "hostgroup"]:
                        if keytab[perm][mode][key]:
                            commands.append([
                                name,
                                "service_%s_%s_keytab" % (mode, perm),
                                keytab[perm][mode]
                            ])
                            break

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

        # Execute commands
        changed = ansible_module.execute_ipa_commands(
            commands, fail_on_member_errors=True)

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