mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Add support for re-enrolling hosts using keytab
A host that has been recreated and does not have its host entry disabled or removed, can be re-enrolled using a previously backed up keytab file. A new option --keytab has been added to ipa-client-install. This can be used to specify path to the keytab and can be used instead of -p or -w options. A new option -f has been added to ipa-join. It forces client to join even if the host entry already exits. A new certificate, ssh keys are generated, ipaUniqueID stays the same. Design page: http://freeipa.org/page/V3/Client_install_using_keytab https://fedorahosted.org/freeipa/ticket/3374
This commit is contained in:
parent
91606e6679
commit
a38d93f65f
@ -104,6 +104,8 @@ def parse_options():
|
||||
help="principal to use to join the IPA realm"),
|
||||
basic_group.add_option("-w", "--password", dest="password", sensitive=True,
|
||||
help="password to join the IPA realm (assumes bulk password unless principal is also set)"),
|
||||
basic_group.add_option("-k", "--keytab", dest="keytab",
|
||||
help="path to backed up keytab from previous enrollment"),
|
||||
basic_group.add_option("-W", dest="prompt_password", action="store_true",
|
||||
default=False,
|
||||
help="Prompt for a password to join the IPA realm"),
|
||||
@ -1691,8 +1693,12 @@ def install(options, env, fstore, statestore):
|
||||
except ipaclient.ntpconf.NTPConfigurationError:
|
||||
pass
|
||||
|
||||
if options.unattended and (options.password is None and options.principal is None and options.prompt_password is False) and not options.on_master:
|
||||
root_logger.error("One of password and principal are required.")
|
||||
if options.unattended and (options.password is None and
|
||||
options.principal is None and
|
||||
options.keytab is None and
|
||||
options.prompt_password is False and
|
||||
not options.on_master):
|
||||
root_logger.error("One of password / principal / keytab is required.")
|
||||
return CLIENT_INSTALL_ERROR
|
||||
|
||||
if options.hostname:
|
||||
@ -1910,8 +1916,10 @@ def install(options, env, fstore, statestore):
|
||||
ipaservices.backup_and_replace_hostname(fstore, statestore, options.hostname)
|
||||
|
||||
if not options.unattended:
|
||||
if options.principal is None and options.password is None and options.prompt_password is False:
|
||||
options.principal = user_input("User authorized to enroll computers", allow_empty=False)
|
||||
if (options.principal is None and options.password is None and
|
||||
options.prompt_password is False and options.keytab is None):
|
||||
options.principal = user_input("User authorized to enroll "
|
||||
"computers", allow_empty=False)
|
||||
root_logger.debug(
|
||||
"will use principal provided as option: %s", options.principal)
|
||||
|
||||
@ -1985,12 +1993,34 @@ def install(options, env, fstore, statestore):
|
||||
else:
|
||||
stdin = sys.stdin.readline()
|
||||
|
||||
(stderr, stdout, returncode) = run(["kinit", principal], raiseonerr=False, stdin=stdin, env=env)
|
||||
(stderr, stdout, returncode) = run(["kinit", principal],
|
||||
raiseonerr=False,
|
||||
stdin=stdin,
|
||||
env=env)
|
||||
if returncode != 0:
|
||||
root_logger.error("Kerberos authentication failed")
|
||||
root_logger.info("%s", stdout)
|
||||
print_port_conf_info()
|
||||
return CLIENT_INSTALL_ERROR
|
||||
elif options.keytab:
|
||||
join_args.append("-f")
|
||||
if os.path.exists(options.keytab):
|
||||
(stderr, stdout, returncode) = run(
|
||||
['/usr/bin/kinit','-k', '-t', options.keytab,
|
||||
'host/%s@%s' % (hostname, cli_realm)],
|
||||
env=env,
|
||||
raiseonerr=False)
|
||||
|
||||
if returncode != 0:
|
||||
root_logger.error("Kerberos authentication failed "
|
||||
"using keytab: %s", options.keytab)
|
||||
root_logger.info("%s", stdout)
|
||||
print_port_conf_info()
|
||||
return CLIENT_INSTALL_ERROR
|
||||
else:
|
||||
root_logger.error("Keytab file could not be found: %s"
|
||||
% options.keytab)
|
||||
return CLIENT_INSTALL_ERROR
|
||||
elif options.password:
|
||||
nolog = (options.password,)
|
||||
join_args.append("-w")
|
||||
|
@ -558,7 +558,7 @@ done:
|
||||
}
|
||||
|
||||
static int
|
||||
join_krb5(const char *ipaserver, char *hostname, char **hostdn, const char **princ, const char **subject, int quiet) {
|
||||
join_krb5(const char *ipaserver, char *hostname, char **hostdn, const char **princ, const char **subject, int force, int quiet) {
|
||||
xmlrpc_env env;
|
||||
xmlrpc_value * argArrayP = NULL;
|
||||
xmlrpc_value * paramArrayP = NULL;
|
||||
@ -663,7 +663,7 @@ join_krb5(const char *ipaserver, char *hostname, char **hostdn, const char **pri
|
||||
goto cleanup;
|
||||
}
|
||||
xmlrpc_struct_find_value(&env, structP, "krblastpwdchange", &krblastpwdchangeP);
|
||||
if (krblastpwdchangeP) {
|
||||
if (krblastpwdchangeP && !force) {
|
||||
xmlrpc_value * singleprincP = NULL;
|
||||
|
||||
/* FIXME: all values are returned as lists currently. Once this is
|
||||
@ -929,7 +929,7 @@ cleanup:
|
||||
|
||||
|
||||
static int
|
||||
join(const char *server, const char *hostname, const char *bindpw, const char *basedn, const char *keytab, int quiet)
|
||||
join(const char *server, const char *hostname, const char *bindpw, const char *basedn, const char *keytab, int force, int quiet)
|
||||
{
|
||||
int rval = 0;
|
||||
pid_t childpid = 0;
|
||||
@ -1003,7 +1003,8 @@ join(const char *server, const char *hostname, const char *bindpw, const char *b
|
||||
rval = 6;
|
||||
goto cleanup;
|
||||
}
|
||||
rval = join_krb5(ipaserver, host, &hostdn, &princ, &subject, quiet);
|
||||
rval = join_krb5(ipaserver, host, &hostdn, &princ, &subject, force,
|
||||
quiet);
|
||||
}
|
||||
|
||||
if (rval) goto cleanup;
|
||||
@ -1100,6 +1101,7 @@ main(int argc, const char **argv) {
|
||||
static const char *basedn = NULL;
|
||||
int quiet = 0;
|
||||
int unenroll = 0;
|
||||
int force = 0;
|
||||
struct poptOption options[] = {
|
||||
{ "debug", 'd', POPT_ARG_NONE, &debug, 0,
|
||||
_("Print the raw XML-RPC output in GSSAPI mode"), NULL },
|
||||
@ -1113,6 +1115,8 @@ main(int argc, const char **argv) {
|
||||
_("IPA Server to use"), _("hostname") },
|
||||
{ "keytab", 'k', POPT_ARG_STRING, &keytab, 0,
|
||||
_("Specifies where to store keytab information."), _("filename") },
|
||||
{ "force", 'f', POPT_ARG_NONE, &force, 0,
|
||||
_("Force the host join. Rejoin even if already joined."), NULL },
|
||||
{ "bindpw", 'w', POPT_ARG_STRING, &bindpw, 0,
|
||||
_("LDAP password (if not using Kerberos)"), _("password") },
|
||||
{ "basedn", 'b', POPT_ARG_STRING, &basedn, 0,
|
||||
@ -1149,7 +1153,7 @@ main(int argc, const char **argv) {
|
||||
} else {
|
||||
ret = check_perms(keytab);
|
||||
if (ret == 0)
|
||||
ret = join(server, hostname, bindpw, basedn, keytab, quiet);
|
||||
ret = join(server, hostname, bindpw, basedn, keytab, force, quiet);
|
||||
}
|
||||
|
||||
exit(ret);
|
||||
|
@ -76,6 +76,9 @@ Password for joining a machine to the IPA realm. Assumes bulk password unless pr
|
||||
\fB\-W\fR
|
||||
Prompt for the password for joining a machine to the IPA realm.
|
||||
.TP
|
||||
\fB\-k\fR, \fB\-\-keytab\fR
|
||||
Path to backed up host keytab from previous enrollment.
|
||||
.TP
|
||||
\fB\-\-mkhomedir\fR
|
||||
Configure PAM to create a users home directory if it does not exist.
|
||||
.TP
|
||||
|
@ -64,6 +64,9 @@ The password to use if not using Kerberos to authenticate. Use a password of thi
|
||||
\fB\-b,\-\-basedn basedn\fR
|
||||
The basedn of the IPA server (of the form dc=example,dc=com). This is only needed when not using Kerberos to authenticate and anonymous binds are disallowed in the IPA LDAP server.
|
||||
.TP
|
||||
\fB\-f,\-\-force\fR
|
||||
Force enrolling the host even if host entry exists.
|
||||
.TP
|
||||
\fB\-u,\-\-unenroll\fR
|
||||
Unenroll this host from the IPA server. No keytab entry is removed in the process
|
||||
(see
|
||||
|
Loading…
Reference in New Issue
Block a user