summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xipa-client/ipa-install/ipa-client-install67
-rw-r--r--ipapython/certmonger.py80
2 files changed, 134 insertions, 13 deletions
diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install
index 390e60037..720e81353 100755
--- a/ipa-client/ipa-install/ipa-client-install
+++ b/ipa-client/ipa-install/ipa-client-install
@@ -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:
diff --git a/ipapython/certmonger.py b/ipapython/certmonger.py
index 15ae1e52f..1ed907686 100644
--- a/ipapython/certmonger.py
+++ b/ipapython/certmonger.py
@@ -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')