If --hostname is provided for ipa-client-install use it everywhere.

If a hostname was provided it wasn't used to configure either
certmonger or sssd. This resulted in a non-working configuration.

Additionally on un-enrollment the wrong hostname was unenrolled, it
used the value of gethostname() rather than the one that was passed
into the installer.

We have to modify the CA configuration of certmonger to make it
use the right principal when requesting certificates. The filename
is unpredicable but it will be in /var/lib/certmonger/cas.
We need to hunt for ipa_submit and add -k <principal> to it, then
undo that on uninstall. These files are created the first time
the certmonger service starts, so start and stop it before messing
with them.

ticket 1029
This commit is contained in:
Rob Crittenden
2011-03-04 17:53:42 -05:00
parent 61d70657ab
commit 3735450ab8
2 changed files with 134 additions and 13 deletions

View File

@@ -49,7 +49,7 @@ error was:
""" % sys.exc_value
sys.exit(1)
client_nss_nickname = 'IPA Machine Certificate - %s' % socket.getfqdn()
client_nss_nickname_format = 'IPA Machine Certificate - %s'
def parse_options():
parser = IPAOptionParser(version=version.VERSION)
@@ -186,6 +186,28 @@ def uninstall(options, env):
print "IPA client is not configured on this system."
return 2
sssdconfig = SSSDConfig.SSSDConfig()
sssdconfig.import_config()
domains = sssdconfig.list_active_domains()
hostname = None
for name in domains:
domain = sssdconfig.get_domain(name)
try:
provider = domain.get_option('id_provider')
except SSSDConfig.NoOptionError:
continue
if provider == "ipa":
try:
hostname = domain.get_option('ipa_hostname')
except SSSDConfig.NoOptionError:
continue
if hostname is None:
hostname = socket.getfqdn()
client_nss_nickname = client_nss_nickname_format % hostname
# Remove our host cert and CA cert
if nickname_exists("IPA CA"):
try:
@@ -214,6 +236,9 @@ def uninstall(options, env):
except:
pass
# Remove any special principal names we added to the IPA CA helper
certmonger.remove_principal_from_cas()
try:
chkconfig('certmonger', 'off')
except:
@@ -221,7 +246,7 @@ def uninstall(options, env):
if not options.on_master:
print "Unenrolling client from IPA server"
join_args = ["/usr/sbin/ipa-join", "--unenroll"]
join_args = ["/usr/sbin/ipa-join", "--unenroll", "-h", hostname]
(stdout, stderr, returncode) = run(join_args, raiseonerr=False, env=env)
if returncode != 0:
print "Unenrolling host failed: %s" % stderr
@@ -453,8 +478,27 @@ def configure_krb5_conf(fstore, cli_basedn, cli_realm, cli_domain, cli_server, d
return 0
def configure_certmonger(fstore, subject_base, cli_realm, options):
def configure_certmonger(fstore, subject_base, cli_realm, hostname, options):
started = True
principal = 'host/%s@%s' % (hostname, cli_realm)
# Ensure that certmonger has been started at least once to generate the
# cas files in /var/lib/certmonger/cas.
try:
service('certmonger', 'restart')
except:
pass
if options.hostname:
# It needs to be stopped if we touch them
try:
service('certmonger', 'stop')
except:
pass
# If the hostname is explicitly set then we need to tell certmonger
# which principal name to use when requesting certs.
certmonger.add_principal_to_cas(principal)
try:
service('certmonger', 'restart')
@@ -471,8 +515,8 @@ def configure_certmonger(fstore, subject_base, cli_realm, options):
# Request our host cert
if started:
subject = 'CN=%s,%s' % (socket.getfqdn(), subject_base)
principal = 'host/%s@%s' % (socket.getfqdn(), cli_realm)
client_nss_nickname = client_nss_nickname_format % hostname
subject = 'CN=%s,%s' % (hostname, subject_base)
try:
run(["ipa-getcert", "request", "-d", "/etc/pki/nssdb", "-n", client_nss_nickname, "-N", subject, "-K", principal])
except:
@@ -488,6 +532,8 @@ def configure_sssd_conf(fstore, cli_realm, cli_domain, cli_server, options):
domain.set_option('ipa_server', '_srv_, %s' % cli_server)
domain.set_option('ipa_domain', cli_domain)
if options.hostname:
domain.set_option('ipa_hostname', options.hostname)
if cli_domain.lower() != cli_realm.lower():
domain.set_option('krb5_realm', cli_realm)
@@ -834,6 +880,10 @@ def main():
# Add the CA to the default NSS database and trust it
run(["/usr/bin/certutil", "-A", "-d", "/etc/pki/nssdb", "-n", "IPA CA", "-t", "CT,C,C", "-a", "-i", "/etc/ipa/ca.crt"])
if options.hostname:
hostname = options.hostname
else:
hostname = socket.getfqdn()
# If on master assume kerberos is already configured properly.
if not options.on_master:
@@ -844,15 +894,10 @@ def main():
print "Configured /etc/krb5.conf for IPA realm " + cli_realm
configure_certmonger(fstore, subject_base, cli_realm, options)
configure_certmonger(fstore, subject_base, cli_realm, hostname, options)
#Try to update the DNS records, failure is not fatal
if not options.on_master:
if options.hostname:
hostname = options.hostname
else:
hostname = socket.gethostname()
client_dns(cli_server, hostname, options.dns_updates)
if options.sssd:

View File

@@ -27,6 +27,7 @@ import time
from ipapython import ipautil
REQUEST_DIR='/var/lib/certmonger/requests/'
CA_DIR='/var/lib/certmonger/cas/'
def find_request_value(filename, directive):
"""
@@ -34,7 +35,7 @@ def find_request_value(filename, directive):
It tries to do this a number of times because sometimes there is a delay
when ipa-getcert returns and the file is fully updated, particularly
when doing a request. Genrerating a CSR is fast but not instantaneous.
when doing a request. Generating a CSR is fast but not instantaneous.
"""
tries = 1
value = None
@@ -126,7 +127,7 @@ def add_request_value(request_id, directive, value):
def add_principal(request_id, principal):
"""
In order for a certmonger request to be renwable it needs a principal.
In order for a certmonger request to be renewable it needs a principal.
When an existing certificate is added via start-tracking it won't have
a principal.
@@ -241,6 +242,81 @@ def stop_tracking(secdir, request_id=None, nickname=None):
return (stdout, stderr, returncode)
def _find_IPA_ca():
"""
Look through all the certmonger CA files to find the one that
has id=IPA
We can use find_request_value because the ca files have the
same file format.
"""
fileList=os.listdir(CA_DIR)
for file in fileList:
value = find_request_value('%s/%s' % (CA_DIR, file), 'id')
if value is not None and value.strip() == 'IPA':
return '%s/%s' % (CA_DIR, file)
return None
def add_principal_to_cas(principal):
"""
If the hostname we were passed to use in ipa-client-install doesn't
match the value of gethostname() then we need to append
-k host/HOSTNAME@REALM to the ca helper defined for
/usr/libexec/certmonger/ipa-submit.
We also need to restore this on uninstall.
The certmonger service MUST be stopped in order for this to work.
"""
cafile = _find_IPA_ca()
if cafile is None:
return
update = False
fp = open(cafile, 'r')
lines = fp.readlines()
fp.close()
for i in xrange(len(lines)):
if lines[i].startswith('ca_external_helper') and \
lines[i].find('-k') == -1:
lines[i] = '%s -k %s\n' % (lines[i].strip(), principal)
update = True
if update:
fp = open(cafile, 'w')
for line in lines:
fp.write(line)
fp.close()
def remove_principal_from_cas():
"""
Remove any -k principal options from the ipa_submit helper.
The certmonger service MUST be stopped in order for this to work.
"""
cafile = _find_IPA_ca()
if cafile is None:
return
update = False
fp = open(cafile, 'r')
lines = fp.readlines()
fp.close()
for i in xrange(len(lines)):
if lines[i].startswith('ca_external_helper') and \
lines[i].find('-k') > 0:
lines[i] = lines[i].strip().split(' ')[0] + '\n'
update = True
if update:
fp = open(cafile, 'w')
for line in lines:
fp.write(line)
fp.close()
if __name__ == '__main__':
request_id = request_cert("/etc/httpd/alias", "Test", "cn=tiger.example.com,O=IPA", "HTTP/tiger.example.com@EXAMPLE.COM")
csr = get_request_value(request_id, 'csr')