X-Git-Url: http://git.cascardo.info/?p=cascardo%2Fipsilon.git;a=blobdiff_plain;f=ipsilon%2Fhelpers%2Fipa.py;h=9c786f90924a2df53e413fcef2cac1076ae1c3a2;hp=df6717f0a5b93eecdebe5e0db63174af7ec03b9a;hb=485baf6ee7a315d1af1086fe5b5da8cff6c4ba37;hpb=33d8af8c15d28a32c42f056546cf391b2cffa803 diff --git a/ipsilon/helpers/ipa.py b/ipsilon/helpers/ipa.py old mode 100755 new mode 100644 index df6717f..9c786f9 --- a/ipsilon/helpers/ipa.py +++ b/ipsilon/helpers/ipa.py @@ -1,28 +1,12 @@ -#!/usr/bin/python -# -# Copyright (C) 2014 Simo Sorce -# -# see file 'COPYING' for use and warranty information -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . +# Copyright (C) 2014 Ipsilon project Contributors, for license see COPYING import logging 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 +28,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 +63,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,66 +77,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: - if os.path.exists(opts['krb_httpd_keytab']): + 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: + logger.info(msg + "... Not found!") + msg = "Searching for keytab in: %s" % HTTPD_IPA_KEYTAB if os.path.exists(HTTPD_IPA_KEYTAB): - opts['krb_httpd_keytab'] = HTTPD_IPA_KEYTAB + opts['gssapi_httpd_keytab'] = HTTPD_IPA_KEYTAB + logger.info(msg + "... Found!") return + else: + 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: - try: - server = srv - c = ipaldap.IPAdmin(host=server) - c.do_sasl_gssapi_bind() - del c - 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['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): + def configure_server(self, opts, changes): if opts['ipa'] != 'yes' and opts['ipa'] != 'auto': return + if opts['ipa'] != 'yes' and opts['gssapi'] == 'no': + return self.logger = logging.getLogger() @@ -159,12 +175,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')