Merge "Improve compatibility with IPA v4.5.0+"

This commit is contained in:
Jenkins 2017-09-08 05:21:28 +00:00 committed by Gerrit Code Review
commit 313569bfa9
2 changed files with 66 additions and 10 deletions

View File

@ -34,6 +34,7 @@ from ipapython.ipautil import realm_to_suffix
from ipapython.ipautil import run
from ipapython.ipautil import user_input
from ipapython.ipautil import write_tmp_file
from ipapython import version
from novajoin.errors import ConfigurationError
try:
@ -48,6 +49,9 @@ except ImportError:
# The import moved in freeIPA 4.5.0
from ipalib.install.kinit import kinit_password
if version.NUM_VERSION >= 40500:
from cryptography.hazmat.primitives import serialization
import nss.nss as nss
logger = logging.getLogger()
@ -135,12 +139,21 @@ class NovajoinRole(object):
def _get_ca_certs(self, server, realm):
basedn = realm_to_suffix(realm)
try:
conn = ipaldap.IPAdmin(server, sasl_nocanon=True)
conn.do_sasl_gssapi_bind()
certs = certstore.get_ca_certs(conn, basedn, realm, False)
except Exception as e:
raise ConfigurationError("get_ca_certs_from_ldap() error: %s" % e)
if version.NUM_VERSION >= 40500:
ldap_uri = ipaldap.get_ldap_uri(server)
try:
conn = ipaldap.LDAPClient(ldap_uri, sasl_nocanon=True)
conn.gssapi_bind()
certs = certstore.get_ca_certs(conn, basedn, realm, False)
except Exception as e:
raise ConfigurationError("get_ca_certs() error: %s" % e)
else:
try:
conn = ipaldap.IPAdmin(server, sasl_nocanon=True)
conn.do_sasl_gssapi_bind()
certs = certstore.get_ca_certs(conn, basedn, realm, False)
except Exception as e:
raise ConfigurationError("get_ca_certs() error: %s" % e)
certs = [x509.load_certificate(c[0], x509.DER) for c in certs
if c[2] is not False]
@ -148,6 +161,13 @@ class NovajoinRole(object):
return certs
def create_nssdb(self, server, realm):
"""Retrieve IPA CA certificate chain to NSS database.
Retrieve the CA cert chain from IPA and add it to a
temporary NSS database and return the path to it.
NOTE: For IPA v4.4.0.
"""
nss.nss_init_nodb()
nss_db = certdb.NSSDatabase()
@ -166,6 +186,26 @@ class NovajoinRole(object):
return nss_db
def create_cafile(self, server, realm):
"""Retrieve IPA CA certificate chain to a file
Retrieve the CA cert chain from IPA and add it to a
temporary file and return the name of the file.
The caller is responsible for removing the temporary file.
NOTE: For IPA v4.5.0+
"""
(cafile_fd, cafile_name) = tempfile.mkstemp()
os.close(cafile_fd)
ca_certs = self._get_ca_certs(server, realm)
ca_certs = [cert.public_bytes(serialization.Encoding.PEM)
for cert in ca_certs]
x509.write_certificate_list(ca_certs, cafile_name)
return cafile_name
def kinit(self, principal, realm, password, config=None):
ccache_dir = tempfile.mkdtemp(prefix='krbcc')
self.ccache_name = os.path.join(ccache_dir, 'ccache')
@ -262,7 +302,10 @@ class NovajoinRole(object):
def _add_host(self, filename):
logging.debug('Add host %s', self.hostname)
otp = ipa_generate_password(allowed_chars)
if version.NUM_VERSION >= 40500:
otp = ipa_generate_password(special=None)
else:
otp = ipa_generate_password(allowed_chars)
self._call_ipa(u'host_add', six.text_type(self.hostname),
{'description': u'Undercloud host',

View File

@ -19,6 +19,7 @@ import os
import shutil
import sys
from ipalib import api, errors
from ipapython import version
from ipapython.ipa_log_manager import log_mgr
from novajoin import configure_ipa
from novajoin.errors import ConfigurationError
@ -87,16 +88,26 @@ if __name__ == '__main__':
os.remove(krb5_conf)
nss_db = None
cafile = None
if precreate_opts_specified:
nss_db = novajoin.create_nssdb(opts.server, opts.realm)
args['nss_dir'] = unicode(nss_db.secdir)
# IPA v4.5.0 switched client from NSS to OpenSSL
if version.NUM_VERSION >= 40500:
cafile = novajoin.create_cafile(opts.server, opts.realm)
# Workaround for https://pagure.io/freeipa/issue/7145
args['tls_ca_cert'] = cafile.decode('UTF-8')
else:
nss_db = novajoin.create_nssdb(opts.server, opts.realm)
args['nss_dir'] = nss_db.secdir.decode('UTF-8')
api.bootstrap(**args)
api.finalize()
logging.debug('Connect to IPA backend')
try:
if nss_db:
if cafile:
api.Backend.rpcclient.connect(ca_certfile=cafile)
elif nss_db:
api.Backend.rpcclient.connect(nss_dir=nss_db.secdir)
else:
api.Backend.rpcclient.connect()
@ -109,6 +120,8 @@ if __name__ == '__main__':
if nss_db:
nss_db.close()
if cafile:
os.remove(cafile)
if krb5_conf:
os.remove(krb5_conf)
if ccache_dir: