ipa-client-install: try to get host TGT several times before giving up

New option '--kinit-attempts' enables the host to make multiple attempts to
obtain host TGT from master before giving up and aborting client installation.

In addition, all kinit attempts were replaced by calls to
'ipautil.kinit_keytab' and 'ipautil.kinit_password'.

https://fedorahosted.org/freeipa/ticket/4808

Reviewed-By: Jan Cholasta <jcholast@redhat.com>
Reviewed-By: Simo Sorce <ssorce@redhat.com>
Reviewed-By: Petr Spacek <pspacek@redhat.com>
This commit is contained in:
Martin Babinsky
2015-03-16 16:30:55 +01:00
committed by Jan Cholasta
parent 415a5ff372
commit a8e30e9671
2 changed files with 48 additions and 29 deletions

View File

@@ -31,6 +31,7 @@ try:
from ConfigParser import RawConfigParser
from optparse import SUPPRESS_HELP, OptionGroup, OptionValueError
import shutil
from krbV import Krb5Error
import nss.nss as nss
import SSSDConfig
@@ -91,6 +92,14 @@ def parse_options():
parser.values.ca_cert_file = value
def kinit_attempts_callback(option, opt, value, parser):
if value < 1:
raise OptionValueError(
"Option %s expects an integer greater than 0."
% opt)
parser.values.kinit_attempts = value
parser = IPAOptionParser(version=version.VERSION)
basic_group = OptionGroup(parser, "basic options")
@@ -144,6 +153,11 @@ def parse_options():
help="do not modify the nsswitch.conf and PAM configuration")
basic_group.add_option("-f", "--force", dest="force", action="store_true",
default=False, help="force setting of LDAP/Kerberos conf")
basic_group.add_option('--kinit-attempts', dest='kinit_attempts',
action='callback', type='int', default=5,
callback=kinit_attempts_callback,
help=("number of attempts to obtain host TGT"
" (defaults to %default)."))
basic_group.add_option("-d", "--debug", dest="debug", action="store_true",
default=False, help="print debugging information")
basic_group.add_option("-U", "--unattended", dest="unattended",
@@ -2354,6 +2368,7 @@ def install(options, env, fstore, statestore):
root_logger.debug(
"will use principal provided as option: %s", options.principal)
host_principal = 'host/%s@%s' % (hostname, cli_realm)
if not options.on_master:
nolog = tuple()
# First test out the kerberos configuration
@@ -2374,7 +2389,6 @@ def install(options, env, fstore, statestore):
env['KRB5_CONFIG'] = krb_name
(ccache_fd, ccache_name) = tempfile.mkstemp()
os.close(ccache_fd)
env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] = ccache_name
join_args = [paths.SBIN_IPA_JOIN,
"-s", cli_server[0],
"-b", str(realm_to_suffix(cli_realm)),
@@ -2412,29 +2426,23 @@ def install(options, env, fstore, statestore):
else:
stdin = sys.stdin.readline()
(stderr, stdout, returncode) = run(["kinit", principal],
raiseonerr=False,
stdin=stdin,
env=env)
if returncode != 0:
try:
ipautil.kinit_password(principal, stdin, ccache_name)
except RuntimeError as e:
print_port_conf_info()
root_logger.error("Kerberos authentication failed")
root_logger.info("%s", stdout)
root_logger.error("Kerberos authentication failed: %s" % e)
return CLIENT_INSTALL_ERROR
elif options.keytab:
join_args.append("-f")
if os.path.exists(options.keytab):
(stderr, stdout, returncode) = run(
[paths.KINIT,'-k', '-t', options.keytab,
'host/%s@%s' % (hostname, cli_realm)],
env=env,
raiseonerr=False)
if returncode != 0:
try:
ipautil.kinit_keytab(host_principal, options.keytab,
ccache_name,
attempts=options.kinit_attempts)
except Krb5Error as e:
print_port_conf_info()
root_logger.error("Kerberos authentication failed "
"using keytab: %s", options.keytab)
root_logger.info("%s", stdout)
root_logger.error("Kerberos authentication failed: %s"
% e)
return CLIENT_INSTALL_ERROR
else:
root_logger.error("Keytab file could not be found: %s"
@@ -2460,6 +2468,7 @@ def install(options, env, fstore, statestore):
join_args.append(password)
nolog = (password,)
env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] = ccache_name
# Get the CA certificate
try:
os.environ['KRB5_CONFIG'] = env['KRB5_CONFIG']
@@ -2504,12 +2513,14 @@ def install(options, env, fstore, statestore):
# only the KDC we're installing under is contacted.
# Other KDCs might not have replicated the principal yet.
# Once we have the TGT, it's usable on any server.
env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] = CCACHE_FILE
try:
run([paths.KINIT, '-k', '-t', paths.KRB5_KEYTAB,
'host/%s@%s' % (hostname, cli_realm)], env=env)
except CalledProcessError, e:
root_logger.error("Failed to obtain host TGT.")
ipautil.kinit_keytab(host_principal, paths.KRB5_KEYTAB,
CCACHE_FILE,
attempts=options.kinit_attempts)
env['KRB5CCNAME'] = os.environ['KRB5CCNAME'] = CCACHE_FILE
except Krb5Error as e:
print_port_conf_info()
root_logger.error("Failed to obtain host TGT: %s" % e)
# failure to get ticket makes it impossible to login and bind
# from sssd to LDAP, abort installation and rollback changes
return CLIENT_INSTALL_ERROR
@@ -2546,16 +2557,16 @@ def install(options, env, fstore, statestore):
return CLIENT_INSTALL_ERROR
root_logger.info("Configured /etc/sssd/sssd.conf")
host_principal = 'host/%s@%s' % (hostname, cli_realm)
if options.on_master:
# If on master assume kerberos is already configured properly.
# Get the host TGT.
os.environ['KRB5CCNAME'] = CCACHE_FILE
try:
run([paths.KINIT, '-k', '-t', paths.KRB5_KEYTAB,
host_principal])
except CalledProcessError, e:
root_logger.error("Failed to obtain host TGT.")
ipautil.kinit_keytab(host_principal, paths.KRB5_KEYTAB,
CCACHE_FILE,
attempts=options.kinit_attempts)
os.environ['KRB5CCNAME'] = CCACHE_FILE
except Krb5Error as e:
root_logger.error("Failed to obtain host TGT: %s" % e)
return CLIENT_INSTALL_ERROR
else:
# Configure krb5.conf

View File

@@ -152,6 +152,14 @@ Do not use Authconfig to modify the nsswitch.conf and PAM configuration.
\fB\-f\fR, \fB\-\-force\fR
Force the settings even if errors occur
.TP
\fB\-\-kinit\-attempts\fR=\fIKINIT_ATTEMPTS\fR
In case of unresponsive KDC (e.g. when enrolling multiple hosts at once in a
heavy load environment) repeat the request for host Kerberos ticket up to a
total number of \fIKINIT_ATTEMPTS\fR times before giving up and aborting client
installation. Default number of attempts is 5. The request is not repeated when
there is a problem with host credentials themselves (e.g. wrong keytab format
or invalid principal) so using this option will not lead to account lockouts.
.TP
\fB\-d\fR, \fB\-\-debug\fR
Print debugging information to stdout
.TP