X-Git-Url: http://git.cascardo.info/?p=cascardo%2Fipsilon.git;a=blobdiff_plain;f=ipsilon%2Fhelpers%2Fipa.py;h=e6f87e8c8604167b10c2246f12d4ba108af17c32;hp=49486247c19ba5102a1c8db8a09cf79ed6ef3675;hb=aa5dc3b417db962a075a092d0d3528010c1059f7;hpb=b93cf2d751e9c6078ee15d30a66d939bbe2f3b9f diff --git a/ipsilon/helpers/ipa.py b/ipsilon/helpers/ipa.py old mode 100755 new mode 100644 index 4948624..e6f87e8 --- a/ipsilon/helpers/ipa.py +++ b/ipsilon/helpers/ipa.py @@ -1,5 +1,3 @@ -#!/usr/bin/python -# # Copyright (C) 2014 Simo Sorce # # see file 'COPYING' for use and warranty information @@ -22,7 +20,8 @@ import pwd import os import socket import subprocess -import sys + +from ipsilon.helpers.common import EnvHelpersInstaller IPA_CONFIG_FILE = '/etc/ipa/default.conf' @@ -44,9 +43,10 @@ failure (see logs) and retry. """ -class Installer(object): +class Installer(EnvHelpersInstaller): - def __init__(self): + def __init__(self, *pargs): + super(Installer, self).__init__() self.name = 'ipa' self.ptype = 'helper' self.logger = None @@ -78,7 +78,7 @@ class Installer(object): self.server = ipaconfig.config.get_server() except Exception, e: # pylint: disable=broad-except - logger.info('IPA tools installation found: [%s]', str(e)) + logger.info('IPA tools installation found: [%s]', e) if opts['ipa'] == 'yes': raise Exception('No IPA installation found!') return @@ -92,82 +92,97 @@ class Installer(object): raise Exception('No IPA tools found!') # Check if we already have a keytab for HTTP - if 'krb_httpd_keytab' in opts: - msg = "Searching for keytab in: %s" % opts['krb_httpd_keytab'] - print >> sys.stdout, msg, - if os.path.exists(opts['krb_httpd_keytab']): - print >> sys.stdout, "... Found!" + if 'gssapi_httpd_keytab' in opts: + msg = "Searching for keytab in: %s" % opts['gssapi_httpd_keytab'] + if os.path.exists(opts['gssapi_httpd_keytab']): + logger.info(msg + "... Found!") return else: - print >> sys.stdout, "... Not found!" + logger.info(msg + "... Not found!") msg = "Searching for keytab in: %s" % HTTPD_IPA_KEYTAB - print >> sys.stdout, msg, if os.path.exists(HTTPD_IPA_KEYTAB): - opts['krb_httpd_keytab'] = HTTPD_IPA_KEYTAB - print >> sys.stdout, "... Found!" + opts['gssapi_httpd_keytab'] = HTTPD_IPA_KEYTAB + logger.info(msg + "... Found!") return else: - print >> sys.stdout, "... Not found!" + logger.info(msg + "... Not found!") us = socket.gethostname() princ = 'HTTP/%s@%s' % (us, self.realm) # Check we have credentials to access server (for keytab) - from ipapython import ipaldap + from ipalib import api from ipalib import errors as ipaerrors - for srv in self.server: - msg = "Testing access to server: %s" % srv - print >> sys.stdout, msg, - try: - server = srv - c = ipaldap.IPAdmin(host=server) - c.do_sasl_gssapi_bind() - del c - print >> sys.stdout, "... Succeeded!" - break - except ipaerrors.ACIError, e: - # usually this error is returned when we have no - # good credentials, ask the user to kinit and retry - print >> sys.stderr, NO_CREDS_FOR_KEYTAB - logger.error('Invalid credentials: [%s]', repr(e)) - raise Exception('Invalid credentials: [%s]', str(e)) - except Exception, e: # pylint: disable=broad-except - # for other exceptions let's try to fail later - pass + api.bootstrap(context='ipsilon_installer') + api.finalize() try: - subprocess.check_output([IPA_COMMAND, 'service-add', princ], - stderr=subprocess.STDOUT) - except subprocess.CalledProcessError, e: - # hopefully this means the service already exists - # otherwise we'll fail later again - logger.info('Error trying to create HTTP service:') - logger.info('Cmd> %s\n%s', e.cmd, e.output) + api.Backend.rpcclient.connect() + logger.debug('Try RPC connection') + api.Backend.rpcclient.forward('ping') + logger.debug("... Succeeded!") + except ipaerrors.KerberosError as e: + logger.error('Invalid credentials: [%s]', repr(e)) + if api.Backend.rpcclient.isconnected(): + api.Backend.rpcclient.disconnect() + raise Exception('Invalid credentials: [%s]' % e) + except ipaerrors.PublicError as e: + logger.error( + 'Cannot connect to the server due to generic error: %s', e) + if api.Backend.rpcclient.isconnected(): + api.Backend.rpcclient.disconnect() + raise Exception('Unable to connect to IPA server: %s' % e) + + # Specify an older version to work on nearly any master. Force is + # set to True so a DNS A record is not required for adding the + # service. + try: + api.Backend.rpcclient.forward( + 'service_add', + unicode(princ), + force=True, + version=u'2.0', + ) + except ipaerrors.DuplicateEntry: + logger.debug('Principal %s already exists', princ) + except ipaerrors.NotFound as e: + logger.error('%s', e) + raise Exception('%s' % e) + except ipaerrors.ACIError as e: + logger.error(NO_CREDS_FOR_KEYTAB) + logger.debug('Invalid credentials: [%s]', repr(e)) + raise Exception('Invalid credentials: [%s]' % e) + finally: + server = api.Backend.rpcclient.api.env.server + if api.Backend.rpcclient.isconnected(): + api.Backend.rpcclient.disconnect() try: msg = "Trying to fetch keytab[%s] for %s" % ( - opts['krb_httpd_keytab'], princ) - print >> sys.stdout, msg, + opts['gssapi_httpd_keytab'], princ) + logger.info(msg) subprocess.check_output([IPA_GETKEYTAB, '-s', server, '-p', princ, - '-k', opts['krb_httpd_keytab']], + '-k', opts['gssapi_httpd_keytab']], stderr=subprocess.STDOUT) except subprocess.CalledProcessError, e: # unfortunately this one is fatal - print >> sys.stderr, FAILED_TO_GET_KEYTAB + logger.error(FAILED_TO_GET_KEYTAB) logger.info('Error trying to get HTTP keytab:') logger.info('Cmd> %s\n%s', e.cmd, e.output) - raise Exception('Missing keytab: [%s]' % str(e)) + raise Exception('Missing keytab: [%s]' % e) # Fixup permissions so only the ipsilon user can read these files pw = pwd.getpwnam(HTTPD_USER) - os.chown(opts['krb_httpd_keytab'], pw.pw_uid, pw.pw_gid) + os.chown(opts['gssapi_httpd_keytab'], pw.pw_uid, pw.pw_gid) def configure_server(self, opts): if opts['ipa'] != 'yes' and opts['ipa'] != 'auto': return + if opts['ipa'] != 'yes' and opts['gssapi'] == 'no': + return self.logger = logging.getLogger() @@ -175,12 +190,12 @@ class Installer(object): self.get_keytab(opts) - # Forcibly use krb then pam modules - if not 'lm_order' in opts: + # Forcibly use gssapi then pam modules + if 'lm_order' not in opts: opts['lm_order'] = [] - opts['krb'] = 'yes' - if 'krb' not in opts['lm_order']: - opts['lm_order'].insert(0, 'krb') - opts['pam'] = 'yes' - if 'pam' not in opts['lm_order']: - opts['lm_order'].append('pam') + opts['gssapi'] = 'yes' + if 'gssapi' not in opts['lm_order']: + opts['lm_order'].insert(0, 'gssapi') + opts['form'] = 'yes' + if not any(lm in opts['lm_order'] for lm in ('form', 'pam')): + opts['lm_order'].append('form')