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
This commit is contained in:
Rob Crittenden 2011-03-14 16:27:19 -04:00
parent a36bc4ee93
commit 861d1bbdca
7 changed files with 99 additions and 43 deletions

View File

@ -167,14 +167,9 @@ def install_ca(config):
print "Please install dogtag and restart the setup program" print "Please install dogtag and restart the setup program"
sys.exit(1) 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 pkcs12_info = None
if ipautil.file_exists(config.dir + "/dscert.p12"): if ipautil.file_exists(config.dir + "/dogtagcert.p12"):
pkcs12_info = (config.dir + "/dscert.p12", pkcs12_info = (config.dir + "/dogtagcert.p12",
config.dir + "/dirsrv_pin.txt") config.dir + "/dirsrv_pin.txt")
cs = cainstance.CADSInstance() cs = cainstance.CADSInstance()
cs.create_instance(config.realm_name, config.host_name, cs.create_instance(config.realm_name, config.host_name,
@ -206,7 +201,7 @@ def install_ca(config):
ca.start() ca.start()
cs.service_name = service_name cs.service_name = service_name
return ca return (ca, cs)
def install_replica_ds(config): def install_replica_ds(config):
dsinstance.check_existing_installation() dsinstance.check_existing_installation()
@ -487,7 +482,7 @@ def main():
ntp.create_instance() ntp.create_instance()
# Configure the CA if necessary # Configure the CA if necessary
CA = install_ca(config) (CA, cs) = install_ca(config)
# Always try to install DNS records # Always try to install DNS records
install_dns_records(config, options) install_dns_records(config, options)
@ -495,19 +490,12 @@ def main():
# Configure dirsrv # Configure dirsrv
ds = install_replica_ds(config) 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: if CA:
CA.ldap_enable('CA', config.host_name, config.dirman_password, CA.ldap_enable('CA', config.host_name, config.dirman_password,
util.realm_to_suffix(config.realm_name)) util.realm_to_suffix(config.realm_name))
cs.add_simple_service('dogtagldap/%s@%s' % (config.host_name, config.realm_name))
# Now we will replace the existing dogtag 389-ds instance NSS cs.add_cert_to_service()
# 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))
install_krb(config, setup_pkinit=options.setup_pkinit) install_krb(config, setup_pkinit=options.setup_pkinit)
install_http(config) install_http(config)

View File

@ -338,6 +338,14 @@ def main():
print "%s" % e print "%s" % e
sys.exit(1) 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: if options.http_pin:
passwd = options.http_pin passwd = options.http_pin
else: else:

View File

@ -754,7 +754,7 @@ def main():
if options.external_cert_file is None: if options.external_cert_file is None:
cs = cainstance.CADSInstance() 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) ca = cainstance.CAInstance(realm_name, certs.NSS_DIR)
if external == 0: if external == 0:
ca.configure_instance(host_name, dm_password, dm_password, ca.configure_instance(host_name, dm_password, dm_password,
@ -817,17 +817,13 @@ def main():
ca.ldap_enable('CA', host_name, dm_password, ca.ldap_enable('CA', host_name, dm_password,
util.realm_to_suffix(realm_name)) 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 # Turn on SSL in the dogtag LDAP instance. This will get restarted
# later, we don't need SSL now. # later, we don't need SSL now.
cs.create_certdb()
cs.enable_ssl() 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 # Create a kerberos instance
if options.pkinit_pin: if options.pkinit_pin:

View File

@ -224,11 +224,13 @@ class CADSInstance(service.Service):
self.sub_dict = None self.sub_dict = None
self.domain = domain_name self.domain = domain_name
self.serverid = None self.serverid = None
self.host_name = None self.fqdn = None
self.dercert = None
self.pkcs12_info = None self.pkcs12_info = None
self.ds_port = None self.ds_port = None
self.master_host = None self.master_host = None
self.nickname = 'Server-Cert' self.nickname = 'Server-Cert'
self.subject_base = None
if realm_name: if realm_name:
self.suffix = util.realm_to_suffix(self.realm_name) self.suffix = util.realm_to_suffix(self.realm_name)
self.__setup_sub_dict() self.__setup_sub_dict()
@ -236,15 +238,18 @@ class CADSInstance(service.Service):
self.suffix = None self.suffix = None
def create_instance(self, realm_name, host_name, domain_name, 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.ds_port = ds_port
self.realm_name = realm_name.upper() self.realm_name = realm_name.upper()
self.serverid = "PKI-IPA" self.serverid = "PKI-IPA"
self.suffix = util.realm_to_suffix(self.realm_name) self.suffix = util.realm_to_suffix(self.realm_name)
self.host_name = host_name self.fqdn = host_name
self.dm_password = dm_password self.dm_password = dm_password
self.domain = domain_name self.domain = domain_name
self.pkcs12_info = pkcs12_info 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.__setup_sub_dict()
self.step("creating directory server user", self.__create_ds_user) self.step("creating directory server user", self.__create_ds_user)
@ -255,7 +260,7 @@ class CADSInstance(service.Service):
def __setup_sub_dict(self): def __setup_sub_dict(self):
server_root = dsinstance.find_server_root() 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(), PASSWORD=self.dm_password, SUFFIX=self.suffix.lower(),
REALM=self.realm_name, USER=PKI_DS_USER, REALM=self.realm_name, USER=PKI_DS_USER,
SERVER_ROOT=server_root, DOMAIN=self.domain, SERVER_ROOT=server_root, DOMAIN=self.domain,
@ -317,8 +322,32 @@ class CADSInstance(service.Service):
# We only handle one server cert # We only handle one server cert
self.nickname = server_certs[0][0] self.nickname = server_certs[0][0]
self.dercert = dsdb.get_cert_from_db(self.nickname) 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): 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 = ipaldap.IPAdmin("127.0.0.1", port=DEFAULT_DSPORT)
conn.simple_bind_s("cn=directory manager", self.dm_password) conn.simple_bind_s("cn=directory manager", self.dm_password)
@ -377,6 +406,11 @@ class CADSInstance(service.Service):
self.chkconfig_off() self.chkconfig_off()
if not serverid is None: 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) dsinstance.erase_ds_instance_data(serverid)
self.service_name="pkids" self.service_name="pkids"
@ -389,6 +423,15 @@ class CADSInstance(service.Service):
logging.critical("failed to delete user %s" % e) logging.critical("failed to delete user %s" % e)
self.service_name = sav_name 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): class CAInstance(service.Service):
""" """
In the self-signed case the CA exists in the NSS_DB database. 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.realm = realm
self.dm_password = None self.dm_password = None
self.admin_password = None self.admin_password = None
self.host_name = None self.fqdn = None
self.pkcs12_info = None self.pkcs12_info = None
self.clone = False self.clone = False
# for external CAs # for external CAs
@ -462,7 +505,7 @@ class CAInstance(service.Service):
chain and actually proceed to create the CA. For step 1 set chain and actually proceed to create the CA. For step 1 set
csr_file. For step 2 set cert_file and cert_chain_file. 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.dm_password = dm_password
self.admin_password = admin_password self.admin_password = admin_password
self.ds_port = ds_port self.ds_port = ds_port
@ -566,7 +609,7 @@ class CAInstance(service.Service):
try: try:
args = ["/usr/bin/perl", "/usr/bin/pkisilent", "ConfigureCA", args = ["/usr/bin/perl", "/usr/bin/pkisilent", "ConfigureCA",
"-cs_hostname", self.host_name, "-cs_hostname", self.fqdn,
"-cs_port", str(ADMIN_SECURE_PORT), "-cs_port", str(ADMIN_SECURE_PORT),
"-client_certdb_dir", self.ca_agent_db, "-client_certdb_dir", self.ca_agent_db,
"-client_certdb_pwd", "'%s'" % self.admin_password, "-client_certdb_pwd", "'%s'" % self.admin_password,
@ -579,7 +622,7 @@ class CAInstance(service.Service):
"-agent_key_size", "2048", "-agent_key_size", "2048",
"-agent_key_type", "rsa", "-agent_key_type", "rsa",
"-agent_cert_subject", "\"CN=ipa-ca-agent,%s\"" % self.subject_base, "-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), "-ldap_port", str(self.ds_port),
"-bind_dn", "\"cn=Directory Manager\"", "-bind_dn", "\"cn=Directory Manager\"",
"-bind_password", "'%s'" % self.dm_password, "-bind_password", "'%s'" % self.dm_password,
@ -594,7 +637,7 @@ class CAInstance(service.Service):
"-token_name", "internal", "-token_name", "internal",
"-ca_subsystem_cert_subject_name", "\"CN=CA Subsystem,%s\"" % self.subject_base, "-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_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_audit_signing_cert_subject_name", "\"CN=CA Audit,%s\"" % self.subject_base,
"-ca_sign_cert_subject_name", "\"CN=Certificate Authority,%s\"" % self.subject_base ] "-ca_sign_cert_subject_name", "\"CN=Certificate Authority,%s\"" % self.subject_base ]
if self.external == 1: if self.external == 1:
@ -757,7 +800,7 @@ class CAInstance(service.Service):
'-p', self.admin_password, '-p', self.admin_password,
'-d', self.ca_agent_db, '-d', self.ca_agent_db,
'-r', '/ca/agent/ca/profileReview?requestId=%s' % self.requestId, '-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,)) (stdout, stderr, returncode) = ipautil.run(args, nolog=(self.admin_password,))
@ -777,7 +820,7 @@ class CAInstance(service.Service):
'-d', self.ca_agent_db, '-d', self.ca_agent_db,
'-e', params, '-e', params,
'-r', '/ca/agent/ca/profileProcess', '-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,)) (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 # Create an RA user in the CA LDAP server and add that user to
# the appropriate groups so it can issue certificates without # the appropriate groups so it can issue certificates without
# manual intervention. # 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.protocol_version=ldap.VERSION3
ld.simple_bind_s("cn=Directory Manager", self.dm_password) ld.simple_bind_s("cn=Directory Manager", self.dm_password)
@ -880,7 +923,7 @@ class CAInstance(service.Service):
def __get_ca_chain(self): def __get_ca_chain(self):
try: try:
return dogtag.get_ca_certchain(ca_host=self.host_name) return dogtag.get_ca_certchain(ca_host=self.fqdn)
except Exception, e: except Exception, e:
raise RuntimeError("Unable to retrieve CA chain: %s" % str(e)) raise RuntimeError("Unable to retrieve CA chain: %s" % str(e))
@ -959,7 +1002,7 @@ class CAInstance(service.Service):
csr = pkcs10.strip_header(stdout) csr = pkcs10.strip_header(stdout)
# Send the request to the CA # Send the request to the CA
conn = httplib.HTTPConnection(self.host_name, 9180) conn = httplib.HTTPConnection(self.fqdn, 9180)
params = urllib.urlencode({'profileId': 'caServerCert', params = urllib.urlencode({'profileId': 'caServerCert',
'cert_request_type': 'pkcs10', 'cert_request_type': 'pkcs10',
'requestor_name': 'IPA Installer', '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='=') installutils.set_directive(caconfig, 'ca.publish.rule.instance.LdapXCertRule.enable', 'false', quotes=False, separator='=')
# Fix the CRL URI in the profile # 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]) ipautil.run(["/sbin/restorecon", publishdir])

View File

@ -497,6 +497,7 @@ class DsInstance(service.Service):
# We only handle one server cert # We only handle one server cert
nickname = server_certs[0][0] nickname = server_certs[0][0]
self.dercert = dsdb.get_cert_from_db(nickname) self.dercert = dsdb.get_cert_from_db(nickname)
dsdb.track_server_cert(nickname, self.principal, dsdb.passwd_fname)
else: else:
nickname = "Server-Cert" nickname = "Server-Cert"
cadb = certs.CertDB(self.realm_name, host_name=self.fqdn, subject_base=self.subject_base) cadb = certs.CertDB(self.realm_name, host_name=self.fqdn, subject_base=self.subject_base)

View File

@ -186,6 +186,7 @@ class HTTPInstance(service.Service):
# We only handle one server cert # We only handle one server cert
nickname = server_certs[0][0] nickname = server_certs[0][0]
self.dercert = db.get_cert_from_db(nickname) self.dercert = db.get_cert_from_db(nickname)
db.track_server_cert(nickname, self.principal, db.passwd_fname)
self.__set_mod_nss_nickname(nickname) self.__set_mod_nss_nickname(nickname)
else: else:

View File

@ -187,6 +187,25 @@ class Service:
self.admin_conn.addEntry(entry) self.admin_conn.addEntry(entry)
return newdn 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): def add_cert_to_service(self):
""" """
Add a certificate to a service Add a certificate to a service