From 861d1bbdca4793fb45fb233d236d3793cc23da36 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Mon, 14 Mar 2011 16:27:19 -0400 Subject: Fix SELinux errors caused by enabling TLS on dogtag 389-ds instance. This fixes 2 AVCS: * One because we are enabling port 7390 because an SSL port must be defined to use TLS On 7389. * We were symlinking to the main IPA 389-ds NSS certificate databsae. Instead generate a separate NSS database and certificate and have certmonger track it separately I also noticed some variable inconsistency in cainstance.py. Everywhere else we use self.fqdn and that was using self.host_name. I found it confusing so I fixed it. ticket 1085 --- install/tools/ipa-replica-install | 26 ++++---------- install/tools/ipa-replica-prepare | 8 +++++ install/tools/ipa-server-install | 14 +++----- ipaserver/install/cainstance.py | 73 +++++++++++++++++++++++++++++++-------- ipaserver/install/dsinstance.py | 1 + ipaserver/install/httpinstance.py | 1 + ipaserver/install/service.py | 19 ++++++++++ 7 files changed, 99 insertions(+), 43 deletions(-) diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install index cfaeaa4a..2bc9a17e 100755 --- a/install/tools/ipa-replica-install +++ b/install/tools/ipa-replica-install @@ -167,14 +167,9 @@ def install_ca(config): print "Please install dogtag and restart the setup program" sys.exit(1) - # We replicate to the master using TLS. In order for this to work we - # need an SSL server cert. To make things easier we'll re-use the - # IPA 389-ds instance certificate loaded directly into the - # dogtag 389-ds instance. Later we will replace the NSS databases with - # symbolic links. pkcs12_info = None - if ipautil.file_exists(config.dir + "/dscert.p12"): - pkcs12_info = (config.dir + "/dscert.p12", + if ipautil.file_exists(config.dir + "/dogtagcert.p12"): + pkcs12_info = (config.dir + "/dogtagcert.p12", config.dir + "/dirsrv_pin.txt") cs = cainstance.CADSInstance() cs.create_instance(config.realm_name, config.host_name, @@ -206,7 +201,7 @@ def install_ca(config): ca.start() cs.service_name = service_name - return ca + return (ca, cs) def install_replica_ds(config): dsinstance.check_existing_installation() @@ -487,7 +482,7 @@ def main(): ntp.create_instance() # Configure the CA if necessary - CA = install_ca(config) + (CA, cs) = install_ca(config) # Always try to install DNS records install_dns_records(config, options) @@ -495,19 +490,12 @@ def main(): # Configure dirsrv ds = install_replica_ds(config) - # We ned to ldap_enable the CA now that DS is up and running + # We need to ldap_enable the CA now that DS is up and running if CA: CA.ldap_enable('CA', config.host_name, config.dirman_password, util.realm_to_suffix(config.realm_name)) - - # Now we will replace the existing dogtag 389-ds instance NSS - # database with a symbolic link to the IPA 389-ds NSS database. - caconfigdir = dsinstance.config_dirname(dsinstance.realm_to_serverid('PKI-IPA')) - for filename in ['cert8.db', 'key3.db', 'secmod.db', 'pin.txt']: - os.unlink('%s%s' % (caconfigdir, filename)) - dsconfigdir = dsinstance.config_dirname(dsinstance.realm_to_serverid(config.realm_name)) - for filename in ['cert8.db', 'key3.db', 'secmod.db', 'pin.txt']: - os.symlink('%s%s' % (dsconfigdir, filename), '%s%s' % (caconfigdir, filename)) + cs.add_simple_service('dogtagldap/%s@%s' % (config.host_name, config.realm_name)) + cs.add_cert_to_service() install_krb(config, setup_pkinit=options.setup_pkinit) install_http(config) diff --git a/install/tools/ipa-replica-prepare b/install/tools/ipa-replica-prepare index 36e34d78..e9122351 100755 --- a/install/tools/ipa-replica-prepare +++ b/install/tools/ipa-replica-prepare @@ -338,6 +338,14 @@ def main(): print "%s" % e sys.exit(1) + if not certs.ipa_self_signed(): + print "Creating SSL certificate for the dogtag Directory Server" + try: + export_certdb(api.env.realm, ds_dir, dir, passwd_fname, "dogtagcert", replica_fqdn, subject_base) + except errors.CertificateOperationError, e: + print "%s" % e + sys.exit(1) + if options.http_pin: passwd = options.http_pin else: diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install index 9c0947c8..f3a01e89 100755 --- a/install/tools/ipa-server-install +++ b/install/tools/ipa-server-install @@ -754,7 +754,7 @@ def main(): if options.external_cert_file is None: cs = cainstance.CADSInstance() - cs.create_instance(realm_name, host_name, domain_name, dm_password) + cs.create_instance(realm_name, host_name, domain_name, dm_password, subject_base=options.subject) ca = cainstance.CAInstance(realm_name, certs.NSS_DIR) if external == 0: ca.configure_instance(host_name, dm_password, dm_password, @@ -817,17 +817,13 @@ def main(): ca.ldap_enable('CA', host_name, dm_password, util.realm_to_suffix(realm_name)) - # Symlink the IPA LDAP server NSS database to this one. - caconfigdir = dsinstance.config_dirname(dsinstance.realm_to_serverid('PKI-IPA')) - for filename in ['cert8.db', 'key3.db', 'secmod.db']: - os.unlink('%s%s' % (caconfigdir, filename)) - dsconfigdir = dsinstance.config_dirname(dsinstance.realm_to_serverid(realm_name)) - for filename in ['cert8.db', 'key3.db', 'secmod.db', 'pin.txt']: - os.symlink('%s%s' % (dsconfigdir, filename), '%s%s' % (caconfigdir, filename)) - # Turn on SSL in the dogtag LDAP instance. This will get restarted # later, we don't need SSL now. + cs.create_certdb() cs.enable_ssl() + # Add the IPA service for storing the PKI-IPA server certificate. + cs.add_simple_service('dogtagldap/%s@%s' % (host_name, realm_name)) + cs.add_cert_to_service() # Create a kerberos instance if options.pkinit_pin: diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py index cb54747f..83f3aa7b 100644 --- a/ipaserver/install/cainstance.py +++ b/ipaserver/install/cainstance.py @@ -224,11 +224,13 @@ class CADSInstance(service.Service): self.sub_dict = None self.domain = domain_name self.serverid = None - self.host_name = None + self.fqdn = None + self.dercert = None self.pkcs12_info = None self.ds_port = None self.master_host = None self.nickname = 'Server-Cert' + self.subject_base = None if realm_name: self.suffix = util.realm_to_suffix(self.realm_name) self.__setup_sub_dict() @@ -236,15 +238,18 @@ class CADSInstance(service.Service): self.suffix = None def create_instance(self, realm_name, host_name, domain_name, - dm_password, pkcs12_info=None, ds_port=DEFAULT_DSPORT): + dm_password, pkcs12_info=None, ds_port=DEFAULT_DSPORT, + subject_base=None): self.ds_port = ds_port self.realm_name = realm_name.upper() self.serverid = "PKI-IPA" self.suffix = util.realm_to_suffix(self.realm_name) - self.host_name = host_name + self.fqdn = host_name self.dm_password = dm_password self.domain = domain_name self.pkcs12_info = pkcs12_info + self.subject_base = subject_base + self.principal = "dogtagldap/%s@%s" % (self.fqdn, self.realm_name) self.__setup_sub_dict() self.step("creating directory server user", self.__create_ds_user) @@ -255,7 +260,7 @@ class CADSInstance(service.Service): def __setup_sub_dict(self): server_root = dsinstance.find_server_root() - self.sub_dict = dict(FQHN=self.host_name, SERVERID=self.serverid, + self.sub_dict = dict(FQHN=self.fqdn, SERVERID=self.serverid, PASSWORD=self.dm_password, SUFFIX=self.suffix.lower(), REALM=self.realm_name, USER=PKI_DS_USER, SERVER_ROOT=server_root, DOMAIN=self.domain, @@ -317,8 +322,32 @@ class CADSInstance(service.Service): # We only handle one server cert self.nickname = server_certs[0][0] self.dercert = dsdb.get_cert_from_db(self.nickname) + dsdb.track_server_cert(self.nickname, self.principal, dsdb.passwd_fname) + + def create_certdb(self): + """ + Create the dogtag 389-ds instance NSS certificate database. This needs + to be done after dogtag is installed and configured. + """ + dirname = dsinstance.config_dirname(self.serverid) + dsdb = certs.CertDB(self.realm_name, nssdir=dirname, subject_base=self.subject_base) + cadb = certs.CertDB(self.realm_name, host_name=self.fqdn, subject_base=self.subject_base) + cadb.export_ca_cert('ipaCert', False) + dsdb.create_from_cacert(cadb.cacert_fname, passwd=None) + self.dercert = dsdb.create_server_cert("Server-Cert", self.fqdn, cadb) + dsdb.track_server_cert("Server-Cert", self.principal, dsdb.passwd_fname) + dsdb.create_pin_file() def enable_ssl(self): + (stdout, stderr, rc) = ipautil.run(["/usr/sbin/semanage", + "port", "-a", + "-t", "ldap_port_t", + "-p", "tcp", + "7390"], raiseonerr=False) + if rc != 0: + if stderr.find('already defined') == -1: + logging.critical("Failed to add SELinux rule for port 7390") + conn = ipaldap.IPAdmin("127.0.0.1", port=DEFAULT_DSPORT) conn.simple_bind_s("cn=directory manager", self.dm_password) @@ -377,6 +406,11 @@ class CADSInstance(service.Service): self.chkconfig_off() if not serverid is None: + # drop the trailing / off the config_dirname so the directory + # will match what is in certmonger + dirname = dsinstance.config_dirname(serverid)[:-1] + dsdb = certs.CertDB(self.realm_name, nssdir=dirname) + dsdb.untrack_server_cert("Server-Cert") dsinstance.erase_ds_instance_data(serverid) self.service_name="pkids" @@ -389,6 +423,15 @@ class CADSInstance(service.Service): logging.critical("failed to delete user %s" % e) self.service_name = sav_name + (stdout, stderr, rc) = ipautil.run(["/usr/sbin/semanage", + "port", "-d", + "-t", "ldap_port_t", + "-p", "tcp", + "7390"], raiseonerr=False) + if rc != 0: + if stderr.find('not defined') == -1: + logging.critical("Failed to remove SELinux rule for port 7390") + class CAInstance(service.Service): """ In the self-signed case the CA exists in the NSS_DB database. @@ -412,7 +455,7 @@ class CAInstance(service.Service): self.realm = realm self.dm_password = None self.admin_password = None - self.host_name = None + self.fqdn = None self.pkcs12_info = None self.clone = False # for external CAs @@ -462,7 +505,7 @@ class CAInstance(service.Service): chain and actually proceed to create the CA. For step 1 set csr_file. For step 2 set cert_file and cert_chain_file. """ - self.host_name = host_name + self.fqdn = host_name self.dm_password = dm_password self.admin_password = admin_password self.ds_port = ds_port @@ -566,7 +609,7 @@ class CAInstance(service.Service): try: args = ["/usr/bin/perl", "/usr/bin/pkisilent", "ConfigureCA", - "-cs_hostname", self.host_name, + "-cs_hostname", self.fqdn, "-cs_port", str(ADMIN_SECURE_PORT), "-client_certdb_dir", self.ca_agent_db, "-client_certdb_pwd", "'%s'" % self.admin_password, @@ -579,7 +622,7 @@ class CAInstance(service.Service): "-agent_key_size", "2048", "-agent_key_type", "rsa", "-agent_cert_subject", "\"CN=ipa-ca-agent,%s\"" % self.subject_base, - "-ldap_host", self.host_name, + "-ldap_host", self.fqdn, "-ldap_port", str(self.ds_port), "-bind_dn", "\"cn=Directory Manager\"", "-bind_password", "'%s'" % self.dm_password, @@ -594,7 +637,7 @@ class CAInstance(service.Service): "-token_name", "internal", "-ca_subsystem_cert_subject_name", "\"CN=CA Subsystem,%s\"" % self.subject_base, "-ca_ocsp_cert_subject_name", "\"CN=OCSP Subsystem,%s\"" % self.subject_base, - "-ca_server_cert_subject_name", "\"CN=%s,%s\"" % (self.host_name, self.subject_base), + "-ca_server_cert_subject_name", "\"CN=%s,%s\"" % (self.fqdn, self.subject_base), "-ca_audit_signing_cert_subject_name", "\"CN=CA Audit,%s\"" % self.subject_base, "-ca_sign_cert_subject_name", "\"CN=Certificate Authority,%s\"" % self.subject_base ] if self.external == 1: @@ -757,7 +800,7 @@ class CAInstance(service.Service): '-p', self.admin_password, '-d', self.ca_agent_db, '-r', '/ca/agent/ca/profileReview?requestId=%s' % self.requestId, - '%s:%d' % (self.host_name, AGENT_SECURE_PORT), + '%s:%d' % (self.fqdn, AGENT_SECURE_PORT), ] (stdout, stderr, returncode) = ipautil.run(args, nolog=(self.admin_password,)) @@ -777,7 +820,7 @@ class CAInstance(service.Service): '-d', self.ca_agent_db, '-e', params, '-r', '/ca/agent/ca/profileProcess', - '%s:%d' % (self.host_name, AGENT_SECURE_PORT), + '%s:%d' % (self.fqdn, AGENT_SECURE_PORT), ] (stdout, stderr, returncode) = ipautil.run(args, nolog=(self.admin_password,)) @@ -821,7 +864,7 @@ class CAInstance(service.Service): # Create an RA user in the CA LDAP server and add that user to # the appropriate groups so it can issue certificates without # manual intervention. - ld = ldap.initialize("ldap://%s:%d" % (self.host_name, self.ds_port)) + ld = ldap.initialize("ldap://%s:%d" % (self.fqdn, self.ds_port)) ld.protocol_version=ldap.VERSION3 ld.simple_bind_s("cn=Directory Manager", self.dm_password) @@ -880,7 +923,7 @@ class CAInstance(service.Service): def __get_ca_chain(self): try: - return dogtag.get_ca_certchain(ca_host=self.host_name) + return dogtag.get_ca_certchain(ca_host=self.fqdn) except Exception, e: raise RuntimeError("Unable to retrieve CA chain: %s" % str(e)) @@ -959,7 +1002,7 @@ class CAInstance(service.Service): csr = pkcs10.strip_header(stdout) # Send the request to the CA - conn = httplib.HTTPConnection(self.host_name, 9180) + conn = httplib.HTTPConnection(self.fqdn, 9180) params = urllib.urlencode({'profileId': 'caServerCert', 'cert_request_type': 'pkcs10', 'requestor_name': 'IPA Installer', @@ -1044,7 +1087,7 @@ class CAInstance(service.Service): installutils.set_directive(caconfig, 'ca.publish.rule.instance.LdapXCertRule.enable', 'false', quotes=False, separator='=') # Fix the CRL URI in the profile - installutils.set_directive('/var/lib/%s/profiles/ca/caIPAserviceCert.cfg' % PKI_INSTANCE_NAME, 'policyset.serverCertSet.9.default.params.crlDistPointsPointName_0', 'https://%s/ipa/crl/MasterCRL.bin' % self.host_name, quotes=False, separator='=') + installutils.set_directive('/var/lib/%s/profiles/ca/caIPAserviceCert.cfg' % PKI_INSTANCE_NAME, 'policyset.serverCertSet.9.default.params.crlDistPointsPointName_0', 'https://%s/ipa/crl/MasterCRL.bin' % self.fqdn, quotes=False, separator='=') ipautil.run(["/sbin/restorecon", publishdir]) diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index 07e15cdf..97b0f8c0 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -497,6 +497,7 @@ class DsInstance(service.Service): # We only handle one server cert nickname = server_certs[0][0] self.dercert = dsdb.get_cert_from_db(nickname) + dsdb.track_server_cert(nickname, self.principal, dsdb.passwd_fname) else: nickname = "Server-Cert" cadb = certs.CertDB(self.realm_name, host_name=self.fqdn, subject_base=self.subject_base) diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py index 4f876c9b..e53c01e1 100644 --- a/ipaserver/install/httpinstance.py +++ b/ipaserver/install/httpinstance.py @@ -186,6 +186,7 @@ class HTTPInstance(service.Service): # We only handle one server cert nickname = server_certs[0][0] self.dercert = db.get_cert_from_db(nickname) + db.track_server_cert(nickname, self.principal, db.passwd_fname) self.__set_mod_nss_nickname(nickname) else: diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py index e97b7816..253c0f05 100644 --- a/ipaserver/install/service.py +++ b/ipaserver/install/service.py @@ -187,6 +187,25 @@ class Service: self.admin_conn.addEntry(entry) return newdn + def add_simple_service(self, principal): + """ + Add a very basic IPA service. + + The principal needs to be fully-formed: service/host@REALM + """ + if not self.admin_conn: + self.ldap_connect() + + dn = "krbprincipalname=%s,cn=services,cn=accounts,%s" % (principal, self.suffix) + hostdn = "fqdn=%s,cn=computers,cn=accounts,%s" % (self.fqdn, self.suffix) + entry = ipaldap.Entry(dn) + entry.setValues("objectclass", ["krbprincipal", "krbprincipalaux", "krbticketpolicyaux", "ipaobject", "ipaservice", "pkiuser"]) + entry.setValue("krbprincipalname", principal) + entry.setValue("ipauniqueid", 'autogenerate') + entry.setValue("managedby", hostdn) + self.admin_conn.addEntry(entry) + return dn + def add_cert_to_service(self): """ Add a certificate to a service -- cgit