Improve compatibility with IPA v4.5.0+
The changes were more significant than just a few imports as initially thought. The RPC API changed signficantly mostly due to switching from NSS to OpenSSL as the crypto layer. Related changes include: * Handling the new random password generator * Writing the CA chain to a file instead of an NSS db * Dealing with certificates having their own object These are handled via the ipapython.version library to tell what version of IPA we have. This cannot rely on the API value because these changes are lower-level. Change-Id: I8ee03edc4b0b2db566db43f2ea64256fe15a3a8b
This commit is contained in:
parent
038e17027d
commit
5ab8dac221
|
@ -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',
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue