summaryrefslogtreecommitdiffstats
path: root/ipaserver
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2009-04-13 13:39:15 -0400
committerRob Crittenden <rcritten@redhat.com>2009-04-20 14:01:00 -0400
commit9182c10b03a7841c9318ad64ae6c5deda77d93d1 (patch)
tree75f7d73a2d1bab18686ddc9e31fe876401c633fe /ipaserver
parentfdf03cb07b6d75eb3cdffbe4cf21cb510134c26d (diff)
downloadfreeipa-9182c10b03a7841c9318ad64ae6c5deda77d93d1.tar.gz
freeipa-9182c10b03a7841c9318ad64ae6c5deda77d93d1.tar.xz
freeipa-9182c10b03a7841c9318ad64ae6c5deda77d93d1.zip
Issue DS and Apache server certs during CA installation.
Notes: - will create a CA instance (pki-ca) if it doesn't exist - maintains support for a self-signed CA - A signing cert is still not created so Firefox autoconfig still won't work
Diffstat (limited to 'ipaserver')
-rw-r--r--ipaserver/install/cainstance.py128
-rw-r--r--ipaserver/install/certs.py254
-rw-r--r--ipaserver/install/dsinstance.py20
-rw-r--r--ipaserver/install/httpinstance.py55
4 files changed, 355 insertions, 102 deletions
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index c402fb04c..088744a48 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -34,11 +34,6 @@ import shutil
import httplib
import urllib
import xml.dom.minidom
-import getopt
-import urlparse
-import getpass
-import socket
-import errno
from nss.error import NSPRError
import nss.nss as nss
@@ -309,7 +304,7 @@ class CADSInstance(service.Service):
if not dsinstance.is_ds_running():
logging.critical("Failed to restart the directory server. See the installation log for details.")
sys.exit(1)
- except Exception, e:
+ except Exception:
# TODO: roll back here?
logging.critical("Failed to restart the directory server. See the installation log for details.")
@@ -341,6 +336,18 @@ class CADSInstance(service.Service):
class CAInstance(service.Service):
+ """
+ In the self-signed case (all done in certs.py) the CA exists in the DS
+ database. When using a dogtag CA the DS database contains just the
+ server cert for DS. The mod_nss database will contain the RA agent
+ cert that will be used to do authenticated requests against dogtag.
+
+ This is done because we use python-nss and will inherit the opened
+ NSS database in mod_python. In nsslib.py we do an nssinit but this will
+ return success if the database is already initialized. It doesn't care
+ if the database is different or not.
+ """
+
def __init__(self):
service.Service.__init__(self, "pki-ca")
self.pki_user = None
@@ -348,10 +355,14 @@ class CAInstance(service.Service):
self.admin_password = None
self.host_name = None
+ # The same database is used for mod_nss because the NSS context
+ # will already have been initialized by Apache by the time
+ # mod_python wants to do things.
+ self.canickname = "CA certificate"
self.basedn = "o=ipaca"
self.ca_agent_db = tempfile.mkdtemp(prefix = "tmp-")
- self.ra_agent_db = "/etc/ipa/ra/alias"
- self.ra_agent_pwd = self.ra_agent_db + "/.pwd"
+ self.ra_agent_db = "/etc/httpd/alias"
+ self.ra_agent_pwd = self.ra_agent_db + "/pwdfile.txt"
self.ds_port = DEFAULT_DSPORT
self.domain_name = "IPA"
self.server_root = "/var/lib"
@@ -368,6 +379,8 @@ class CAInstance(service.Service):
self.admin_password = admin_password
self.ds_port = ds_port
+ if not ipautil.dir_exists("/var/lib/pki-ca"):
+ self.step("creating pki-ca instance", self.create_instance)
self.step("creating certificate server user", self.__create_ca_user)
self.step("configuring certificate server instance", self.__configure_instance)
self.step("creating CA agent PKCS#12 file in /root", self.__create_ca_agent_pkcs12)
@@ -382,6 +395,33 @@ class CAInstance(service.Service):
self.start_creation("Configuring certificate server:")
+ def create_instance(self):
+ """
+ If for some reason the instance doesn't exist, create a new one."
+
+ These values come from /usr/share/pki/ca/setup/postinstall
+ """
+ PKI_INSTANCE_NAME="pki-ca"
+ AGENT_SECURE_PORT="9443"
+ EE_SECURE_PORT="9444"
+ ADMIN_SECURE_PORT="9445"
+ UNSECURE_PORT="9180"
+ TOMCAT_SERVER_PORT="9701"
+
+ args = ['/usr/bin/pkicreate',
+ '-pki_instance_root', '/var/lib',
+ '-pki_instance_name', PKI_INSTANCE_NAME,
+ '-subsystem_type', 'ca',
+ '-agent_secure_port', AGENT_SECURE_PORT,
+ '-ee_secure_port', EE_SECURE_PORT,
+ '-admin_secure_port', ADMIN_SECURE_PORT,
+ '-unsecure_port', UNSECURE_PORT,
+ '-tomcat_server_port', TOMCAT_SERVER_PORT,
+ '-redirect', 'conf=/etc/pki-ca',
+ '-redirect', 'logs=/var/log/pki-ca',
+ ]
+ ipautil.run(args)
+
def __enable(self):
self.backup_state("enabled", self.is_enabled())
self.chkconfig_on()
@@ -500,7 +540,7 @@ class CAInstance(service.Service):
def __restart_instance(self):
try:
self.restart()
- except Exception, e:
+ except Exception:
# TODO: roll back here?
logging.critical("Failed to restart the certificate server. See the installation log for details.")
@@ -526,35 +566,43 @@ class CAInstance(service.Service):
os.remove(admin_name)
# Retrieve the certificate request so we can get the values needed
- # to issue a certificate.
- conn = nsslib.NSSConnection(self.host_name,9443,dbdir=self.ca_agent_db)
- conn.sslsock.set_client_auth_data_callback(client_auth_data_callback, "ipa-ca-agent", self.admin_password, nss.get_default_certdb())
- conn.set_debuglevel(0)
- conn.request("GET", "/ca/agent/ca/profileReview?requestId=7")
- res = conn.getresponse()
- data = res.read()
- if res.status != 200:
- raise RuntimeError("Unable to retrieve certificate request from CA")
-
- data = data.split('\r\n')
+ # to issue a certificate. Use sslget here because this is a
+ # temporary database and nsslib doesn't currently support gracefully
+ # opening and closing an NSS database. This would leave the installer
+ # process stuck using this database during the entire cycle. We need
+ # to use the final RA agent database when issuing certs for DS and
+ # mod_nss.
+ args = [
+ '/usr/bin/sslget',
+ '-n', 'ipa-ca-agent',
+ '-p', self.admin_password,
+ '-d', self.ca_agent_db,
+ '-r', '/ca/agent/ca/profileReview?requestId=7',
+ '%s:%d' % (self.host_name, 9443),
+ ]
+ (stdout, stderr) = ipautil.run(args)
+
+ data = stdout.split('\r\n')
params = get_defList(data)
params['requestId'] = find_substring(data, "requestId")
params['op'] = 'approve'
params['submit'] = 'submit'
params['requestNotes'] = ''
params = urllib.urlencode(params)
- headers = {"Content-type": "application/x-www-form-urlencoded",
- "Accept": "text/plain"}
# Now issue the RA certificate.
- conn.request("POST", "/ca/agent/ca/profileProcess", params, headers)
- res = conn.getresponse()
- data = res.read()
- conn.close()
- if res.status != 200:
- raise RuntimeError("Unable to issue RA certificate")
-
- data = data.split('\r\n')
+ args = [
+ '/usr/bin/sslget',
+ '-n', 'ipa-ca-agent',
+ '-p', self.admin_password,
+ '-d', self.ca_agent_db,
+ '-e', params,
+ '-r', '/ca/agent/ca/profileProcess',
+ '%s:%d' % (self.host_name, 9443),
+ ]
+ (stdout, stderr) = ipautil.run(args)
+
+ data = stdout.split('\r\n')
outputList = get_outputList(data)
self.ra_cert = outputList['b64_cert']
@@ -562,7 +610,7 @@ class CAInstance(service.Service):
self.ra_cert = self.ra_cert.replace('-----BEGIN CERTIFICATE-----','')
self.ra_cert = self.ra_cert.replace('-----END CERTIFICATE-----','')
- # Add the new RA cert to the database in /etc/ipa/ra
+ # Add the new RA cert to the database in /etc/httpd/alias
(agent_fd, agent_name) = tempfile.mkstemp()
os.write(agent_fd, self.ra_cert)
os.close(agent_fd)
@@ -618,8 +666,10 @@ class CAInstance(service.Service):
def __create_ra_agent_db(self):
if ipautil.file_exists(self.ra_agent_db + "/cert8.db"):
- # FIXME, use proper exception
- raise ValueError("The RA Agent database already exists: %s" % self.ra_agent_db)
+ ipautil.backup_file(self.ra_agent_db + "/cert8.db")
+ ipautil.backup_file(self.ra_agent_db + "/key3.db")
+ ipautil.backup_file(self.ra_agent_db + "/secmod.db")
+ ipautil.backup_file(self.ra_agent_db + "/pwdfile.txt")
if not ipautil.dir_exists(self.ra_agent_db):
os.mkdir(self.ra_agent_db)
@@ -647,9 +697,8 @@ class CAInstance(service.Service):
return chain
else:
- # FIXME: raise proper exception
conn.close()
- raise ValueError("Unable to retrieve CA chain")
+ raise RuntimeError("Unable to retrieve CA chain")
def __create_ca_agent_pkcs12(self):
(pwd_fd, pwd_name) = tempfile.mkstemp()
@@ -672,7 +721,7 @@ class CAInstance(service.Service):
os.close(chain_fd)
try:
self.__run_certutil(
- ['-A', '-t', 'CT,C,C', '-n', 'caCert', '-a',
+ ['-A', '-t', 'CT,C,C', '-n', self.canickname, '-a',
'-i', chain_name]
)
finally:
@@ -709,13 +758,14 @@ class CAInstance(service.Service):
res = conn.getresponse()
if res.status == 200:
data = res.read()
+ # FIXME: pull the requestId out so of the response so it isn't
+ # later hard-coded at 7
# print data
conn.close()
else:
conn.close()
- # FIXME: raise proper exception
- raise ValueError("Unable to submit RA cert request")
+ raise RuntimeError("Unable to submit RA cert request")
def __fix_ra_perms(self):
os.chmod(self.ra_agent_db + "/cert8.db", 0640)
@@ -731,7 +781,7 @@ class CAInstance(service.Service):
def uninstall(self):
try:
ipautil.run(["/usr/bin/pkiremove", "-pki_instance_root=/var/lib",
- "-pki_instance_name=pki-ca", "-force"])
+ "-pki_instance_name=pki-ca", "--force"])
except ipautil.CalledProcessError, e:
logging.critical("failed to uninstall CA instance %s" % e)
diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py
index e9061fe11..45958f2ae 100644
--- a/ipaserver/install/certs.py
+++ b/ipaserver/install/certs.py
@@ -22,15 +22,46 @@ import sha
import errno
import tempfile
import shutil
+import logging
+import urllib
+import xml.dom.minidom
+from ipapython import nsslib
from ipapython import sysrestore
from ipapython import ipautil
+from nss.error import NSPRError
+import nss.nss as nss
+
CA_SERIALNO="/var/lib/ipa/ca_serialno"
+def client_auth_data_callback(ca_names, chosen_nickname, password, certdb):
+ cert = None
+ if chosen_nickname:
+ try:
+ cert = nss.find_cert_from_nickname(chosen_nickname, password)
+ priv_key = nss.find_key_by_any_cert(cert, password)
+ return cert, priv_key
+ except NSPRError, e:
+ logging.debug("client auth callback failed %s" % str(e))
+ return False
+ else:
+ nicknames = nss.get_cert_nicknames(certdb, nss.SEC_CERT_NICKNAMES_USER)
+ for nickname in nicknames:
+ try:
+ cert = nss.find_cert_from_nickname(nickname, password)
+ if cert.check_valid_times():
+ if cert.has_signer_in_ca_names(ca_names):
+ priv_key = nss.find_key_by_any_cert(cert, password)
+ return cert, priv_key
+ except NSPRError, e:
+ logging.debug("client auth callback failed %s" % str(e))
+ return False
+ return False
+
class CertDB(object):
- def __init__(self, dir, fstore=None):
- self.secdir = dir
+ def __init__(self, nssdir, fstore=None, host_name=None):
+ self.secdir = nssdir
self.noise_fname = self.secdir + "/noise.txt"
self.passwd_fname = self.secdir + "/pwdfile.txt"
@@ -40,9 +71,16 @@ class CertDB(object):
self.cacert_fname = self.secdir + "/cacert.asc"
self.pk12_fname = self.secdir + "/cacert.p12"
self.pin_fname = self.secdir + "/pin.txt"
+ self.pwd_conf = "/etc/httpd/conf/password.conf"
self.reqdir = tempfile.mkdtemp('', 'ipa-', '/var/lib/ipa')
self.certreq_fname = self.reqdir + "/tmpcertreq"
self.certder_fname = self.reqdir + "/tmpcert.der"
+ self.host_name = host_name
+
+ if ipautil.file_exists(CA_SERIALNO):
+ self.self_signed_ca = True
+ else:
+ self.self_signed_ca = False
# Making this a starting value that will generate
# unique values for the current DB is the
@@ -72,6 +110,22 @@ class CertDB(object):
def __del__(self):
shutil.rmtree(self.reqdir, ignore_errors=True)
+ def find_cert_from_txt(self, cert):
+ """
+ Given a cert blob (str) which may or may not contian leading and
+ trailing text, pull out just the certificate part. This will return
+ the FIRST cert in a stream of data.
+ """
+ s = cert.find('-----BEGIN CERTIFICATE-----')
+ e = cert.find('-----END CERTIFICATE-----')
+ if e > 0: e = e + 25
+
+ if s < 0 or e < 0:
+ raise RuntimeError("Unable to find certificate")
+
+ cert = cert[s:e]
+ return cert
+
def set_serial_from_pkcs12(self):
"""A CA cert was loaded from a PKCS#12 file. Set up our serial file"""
@@ -94,6 +148,7 @@ class CertDB(object):
f.close()
except IOError, e:
if e.errno == errno.ENOENT:
+ self.self_signed_ca = True
self.cur_serial = 1000
f=open(CA_SERIALNO,"w")
f.write(str(self.cur_serial))
@@ -131,7 +186,8 @@ class CertDB(object):
ipautil.run(new_args, stdin)
def create_noise_file(self):
- ipautil.backup_file(self.noise_fname)
+ if ipautil.file_exists(self.noise_fname):
+ os.remove(self.noise_fname)
f = open(self.noise_fname, "w")
f.write(self.gen_password())
self.set_perms(self.noise_fname)
@@ -193,6 +249,14 @@ class CertDB(object):
"-a",
"-i", cacert_fname])
+ def get_cert_from_db(self, nickname):
+ try:
+ args = ["-L", "-n", nickname, "-a"]
+ (cert, err) = self.run_certutil(args)
+ return cert
+ except ipautil.CalledProcessError:
+ return ''
+
def find_cacert_serial(self):
(out,err) = self.run_certutil(["-L", "-n", self.cacert_name])
data = out.split('\n')
@@ -203,11 +267,20 @@ class CertDB(object):
raise RuntimeError("Unable to find serial number")
- def create_server_cert(self, nickname, name, other_certdb=None):
+ def create_server_cert(self, nickname, subject, other_certdb=None):
+ """
+ other_certdb can mean one of two things, depending on the context.
+
+ If we are using a self-signed CA then other_certdb contains the
+ CA that will be signing our CSR.
+
+ If we are using a dogtag CA then it contains the RA agent key
+ that will issue our cert.
+ """
cdb = other_certdb
if not cdb:
cdb = self
- self.request_cert(name)
+ (out, err) = self.request_cert(subject)
cdb.issue_server_cert(self.certreq_fname, self.certder_fname)
self.add_cert(self.certder_fname, nickname)
os.unlink(self.certreq_fname)
@@ -223,41 +296,103 @@ class CertDB(object):
os.unlink(self.certreq_fname)
os.unlink(self.certder_fname)
- def request_cert(self, name):
- self.run_certutil(["-R", "-s", name,
- "-o", self.certreq_fname,
- "-g", self.keysize,
- "-z", self.noise_fname,
- "-f", self.passwd_fname])
+ def request_cert(self, subject, certtype="rsa", keysize="2048"):
+ self.create_noise_file()
+ args = ["-R", "-s", subject,
+ "-o", self.certreq_fname,
+ "-k", certtype,
+ "-g", keysize,
+ "-z", self.noise_fname,
+ "-f", self.passwd_fname]
+ if not self.self_signed_ca:
+ args.append("-a")
+ (stdout, stderr) = self.run_certutil(args)
+ os.remove(self.noise_fname)
+
+ return (stdout, stderr)
def issue_server_cert(self, certreq_fname, cert_fname):
- p = subprocess.Popen(["/usr/bin/certutil",
- "-d", self.secdir,
- "-C", "-c", self.cacert_name,
- "-i", certreq_fname,
- "-o", cert_fname,
- "-m", self.next_serial(),
- "-v", self.valid_months,
- "-f", self.passwd_fname,
- "-1", "-5"],
- stdin=subprocess.PIPE,
- stdout=subprocess.PIPE)
+ if self.self_signed_ca:
+ p = subprocess.Popen(["/usr/bin/certutil",
+ "-d", self.secdir,
+ "-C", "-c", self.cacert_name,
+ "-i", certreq_fname,
+ "-o", cert_fname,
+ "-m", self.next_serial(),
+ "-v", self.valid_months,
+ "-f", self.passwd_fname,
+ "-1", "-5"],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE)
+
+ # Bah - this sucks, but I guess it isn't possible to fully
+ # control this with command line arguments.
+ #
+ # What this is requesting is:
+ # -1 (Create key usage extension)
+ # 2 - Key encipherment
+ # 9 - done
+ # n - not critical
+ #
+ # -5 (Create netscape cert type extension)
+ # 1 - SSL Server
+ # 9 - done
+ # n - not critical
+ p.stdin.write("2\n9\nn\n1\n9\nn\n")
+ p.wait()
+ else:
+ if self.host_name is None:
+ raise RuntimeError("CA Host is not set.")
- # Bah - this sucks, but I guess it isn't possible to fully
- # control this with command line arguments.
- #
- # What this is requesting is:
- # -1 (Create key usage extension)
- # 2 - Key encipherment
- # 9 - done
- # n - not critical
- #
- # -5 (Create netscape cert type extension)
- # 1 - SSL Server
- # 9 - done
- # n - not critical
- p.stdin.write("2\n9\nn\n1\n9\nn\n")
- p.wait()
+ f = open(certreq_fname, "r")
+ csr = f.readlines()
+ f.close()
+ csr = "".join(csr)
+
+ # We just want the CSR bits, make sure there is nothing else
+ s = csr.find("-----BEGIN NEW CERTIFICATE REQUEST-----")
+ e = csr.find("-----END NEW CERTIFICATE REQUEST-----")
+ if e > 0:
+ e = e + 37
+ if s >= 0:
+ csr = csr[s:]
+
+ params = urllib.urlencode({'profileId': 'caRAserverCert',
+ 'cert_request_type': 'pkcs10',
+ 'requestor_name': 'IPA Installer',
+ 'cert_request': csr,
+ 'xmlOutput': 'true'})
+ headers = {"Content-type": "application/x-www-form-urlencoded",
+ "Accept": "text/plain"}
+
+ # Send the CSR request to the CA
+ f = open(self.passwd_fname)
+ password = f.readline()
+ f.close()
+ conn = nsslib.NSSConnection(self.host_name, 9444, dbdir=self.secdir)
+ conn.sslsock.set_client_auth_data_callback(client_auth_data_callback, "ipaCert", password, nss.get_default_certdb())
+ conn.set_debuglevel(0)
+
+ conn.request("POST", "/ca/ee/ca/profileSubmit", params, headers)
+ res = conn.getresponse()
+ data = res.read()
+ conn.close()
+ if res.status != 200:
+ raise RuntimeError("Unable to submit cert request")
+
+ # The result is an XML blob. Pull the certificate out of that
+ doc = xml.dom.minidom.parseString(data)
+ item_node = doc.getElementsByTagName("b64")
+ cert = item_node[0].childNodes[0].data
+ doc.unlink()
+
+ # Write the certificate to a file. It will be imported in a later
+ # step.
+ f = open(cert_fname, "w")
+ f.write(cert)
+ f.close()
+
+ return
def issue_signing_cert(self, certreq_fname, cert_fname):
p = subprocess.Popen(["/usr/bin/certutil",
@@ -290,12 +425,18 @@ class CertDB(object):
p.wait()
def add_cert(self, cert_fname, nickname):
- self.run_certutil(["-A", "-n", nickname,
- "-t", "u,u,u",
- "-i", cert_fname,
- "-f", cert_fname])
+ args = ["-A", "-n", nickname,
+ "-t", "u,u,u",
+ "-i", cert_fname,
+ "-f", cert_fname]
+ if not self.self_signed_ca:
+ args.append("-a")
+ self.run_certutil(args)
def create_pin_file(self):
+ """
+ This is the format of Directory Server pin files.
+ """
ipautil.backup_file(self.pin_fname)
f = open(self.pin_fname, "w")
f.write("Internal (Software) Token:")
@@ -304,6 +445,17 @@ class CertDB(object):
f.close()
self.set_perms(self.pin_fname)
+ def create_password_conf(self):
+ """
+ This is the format of mod_nss pin files.
+ """
+ ipautil.backup_file(self.pwd_conf)
+ f = open(self.pwd_conf, "w")
+ f.write("internal:")
+ pwd = open(self.passwd_fname)
+ f.write(pwd.read())
+ f.close()
+
def find_root_cert(self, nickname):
p = subprocess.Popen(["/usr/bin/certutil", "-d", self.secdir,
"-O", "-n", nickname], stdout=subprocess.PIPE)
@@ -375,7 +527,24 @@ class CertDB(object):
self.create_pin_file()
def create_from_cacert(self, cacert_fname, passwd=""):
- self.create_noise_file()
+ if ipautil.file_exists(self.certdb_fname):
+ # We already have a cert db, see if it is for the same CA.
+ # If it is we leave things as they are.
+ f = open(cacert_fname, "r")
+ newca = f.readlines()
+ f.close()
+ newca = "".join(newca)
+ newca = self.find_cert_from_txt(newca)
+
+ cacert = self.get_cert_from_db(self.cacert_name)
+ if cacert != '':
+ cacert = self.find_cert_from_txt(cacert)
+
+ if newca == cacert:
+ return
+
+ # The CA certificates are different or something went wrong. Start with
+ # a new certificate database.
self.create_passwd_file(passwd)
self.create_certdbs()
self.load_cacert(cacert_fname)
@@ -403,6 +572,7 @@ class CertDB(object):
self.trust_root_cert(nickname)
self.create_pin_file()
self.export_ca_cert(self.cacert_name, False)
+ self.self_signed_ca=False
# This file implies that we have our own self-signed CA. Ensure
# that it no longer exists (from previous installs, for example).
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index d6a386e47..53fca5af0 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -154,7 +154,7 @@ class DsInstance(service.Service):
else:
self.suffix = None
- def create_instance(self, ds_user, realm_name, host_name, domain_name, dm_password, pkcs12_info=None):
+ def create_instance(self, ds_user, realm_name, host_name, domain_name, dm_password, pkcs12_info=None, self_signed_ca=False):
self.ds_user = ds_user
self.realm_name = realm_name.upper()
self.serverid = realm_to_serverid(self.realm_name)
@@ -163,6 +163,7 @@ class DsInstance(service.Service):
self.dm_password = dm_password
self.domain = domain_name
self.pkcs12_info = pkcs12_info
+ self.self_signed_ca = self_signed_ca
self.__setup_sub_dict()
self.step("creating directory server user", self.__create_ds_user)
@@ -341,19 +342,26 @@ class DsInstance(service.Service):
def __enable_ssl(self):
dirname = config_dirname(self.serverid)
- ca = certs.CertDB(dirname)
+ dsdb = certs.CertDB(dirname)
if self.pkcs12_info:
- ca.create_from_pkcs12(self.pkcs12_info[0], self.pkcs12_info[1])
- server_certs = ca.find_server_certs()
+ dsdb.create_from_pkcs12(self.pkcs12_info[0], self.pkcs12_info[1])
+ server_certs = dsdb.find_server_certs()
if len(server_certs) == 0:
raise RuntimeError("Could not find a suitable server cert in import in %s" % pkcs12_info[0])
# We only handle one server cert
nickname = server_certs[0][0]
else:
- ca.create_self_signed()
- ca.create_server_cert("Server-Cert", "cn=%s,ou=Fedora Directory Server" % self.host_name)
nickname = "Server-Cert"
+ if self.self_signed_ca:
+ dsdb.create_self_signed()
+ dsdb.create_server_cert("Server-Cert", "cn=%s,ou=Fedora Directory Server" % self.host_name)
+ else:
+ cadb = certs.CertDB("/etc/httpd/alias", host_name=self.host_name)
+ cadb.export_ca_cert(cadb.cacert_name, False)
+ dsdb.create_from_cacert(cadb.cacert_fname, passwd=None)
+ dsdb.create_server_cert("Server-Cert", "CN=%s,OU=pki-ipa,O=IPA" % self.host_name, cadb)
+ dsdb.create_pin_file()
conn = ipaldap.IPAdmin("127.0.0.1")
conn.simple_bind_s("cn=directory manager", self.dm_password)
diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py
index d4cebfac9..0637e3f45 100644
--- a/ipaserver/install/httpinstance.py
+++ b/ipaserver/install/httpinstance.py
@@ -59,21 +59,25 @@ class HTTPInstance(service.Service):
else:
self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
- def create_instance(self, realm, fqdn, domain_name, autoconfig=True, pkcs12_info=None):
+ def create_instance(self, realm, fqdn, domain_name, autoconfig=True, pkcs12_info=None, self_signed_ca=False):
self.fqdn = fqdn
self.realm = realm
self.domain = domain_name
self.pkcs12_info = pkcs12_info
+ self.self_signed_ca = self_signed_ca
self.sub_dict = { "REALM" : realm, "FQDN": fqdn, "DOMAIN" : self.domain }
self.step("disabling mod_ssl in httpd", self.__disable_mod_ssl)
self.step("Setting mod_nss port to 443", self.__set_mod_nss_port)
+ if not self_signed_ca:
+ self.step("Setting mod_nss password file", self.__set_mod_nss_passwordfile)
self.step("Adding URL rewriting rules", self.__add_include)
self.step("configuring httpd", self.__configure_http)
self.step("creating a keytab for httpd", self.__create_http_keytab)
self.step("Setting up ssl", self.__setup_ssl)
if autoconfig:
self.step("Setting up browser autoconfig", self.__setup_autoconfig)
+ self.step("publish CA cert", self.__publish_ca_cert)
self.step("configuring SELinux for httpd", self.__selinux_config)
self.step("restarting httpd", self.__start)
self.step("configuring httpd to start on boot", self.__enable)
@@ -148,17 +152,23 @@ class HTTPInstance(service.Service):
def __set_mod_nss_nickname(self, nickname):
installutils.set_directive(NSS_CONF, 'NSSNickname', nickname)
+ def __set_mod_nss_passwordfile(self):
+ installutils.set_directive(NSS_CONF, 'NSSPassPhraseDialog', 'file:/etc/httpd/conf/password.conf')
+
def __add_include(self):
"""This should run after __set_mod_nss_port so is already backed up"""
if installutils.update_file(NSS_CONF, '</VirtualHost>', 'Include conf.d/ipa-rewrite.conf\n</VirtualHost>') != 0:
print "Adding Include conf.d/ipa-rewrite to %s failed." % NSS_CONF
def __setup_ssl(self):
- ds_ca = certs.CertDB(dsinstance.config_dirname(dsinstance.realm_to_serverid(self.realm)))
- ca = certs.CertDB(NSS_DIR)
+ if self.self_signed_ca:
+ ca_db = certs.CertDB(dsinstance.config_dirname(dsinstance.realm_to_serverid(self.realm)))
+ else:
+ ca_db = certs.CertDB(NSS_DIR, host_name=self.fqdn)
+ db = certs.CertDB(NSS_DIR)
if self.pkcs12_info:
- ca.create_from_pkcs12(self.pkcs12_info[0], self.pkcs12_info[1], passwd="")
- server_certs = ca.find_server_certs()
+ db.create_from_pkcs12(self.pkcs12_info[0], self.pkcs12_info[1], passwd="")
+ server_certs = db.find_server_certs()
if len(server_certs) == 0:
raise RuntimeError("Could not find a suitable server cert in import in %s" % pkcs12_info[0])
@@ -167,9 +177,13 @@ class HTTPInstance(service.Service):
self.__set_mod_nss_nickname(nickname)
else:
- ca.create_from_cacert(ds_ca.cacert_fname)
- ca.create_server_cert("Server-Cert", "cn=%s,ou=Apache Web Server" % self.fqdn, ds_ca)
- ca.create_signing_cert("Signing-Cert", "cn=%s,ou=Signing Certificate,o=Identity Policy Audit" % self.fqdn, ds_ca)
+ if self.self_signed_ca:
+ db.create_from_cacert(ca_db.cacert_fname)
+ db.create_server_cert("Server-Cert", "cn=%s,ou=Apache Web Server" % self.fqdn, ca_db)
+ db.create_signing_cert("Signing-Cert", "cn=%s,ou=Signing Certificate,o=Identity Policy Audit" % self.fqdn, ca_db)
+ else:
+ db.create_server_cert("Server-Cert", "CN=%s,OU=ipa-pki,O=IPA" % self.fqdn, ca_db)
+ db.create_password_conf()
# Fix the database permissions
os.chmod(NSS_DIR + "/cert8.db", 0640)
@@ -182,27 +196,38 @@ class HTTPInstance(service.Service):
os.chown(NSS_DIR + "/secmod.db", 0, pent.pw_gid )
def __setup_autoconfig(self):
+ # FIXME. Need to issue the self-signed cert from the CA as well.
+ # A special profile is needed from the CS team to do this.
+ if not self.self_signed_ca:
+ return
prefs_txt = ipautil.template_file(ipautil.SHARE_DIR + "preferences.html.template", self.sub_dict)
prefs_fd = open("/usr/share/ipa/html/preferences.html", "w")
prefs_fd.write(prefs_txt)
prefs_fd.close()
# The signing cert is generated in __setup_ssl
- ds_ca = certs.CertDB(dsinstance.config_dirname(dsinstance.realm_to_serverid(self.realm)))
- ca = certs.CertDB(NSS_DIR)
-
- # Publish the CA certificate
- shutil.copy(ds_ca.cacert_fname, "/usr/share/ipa/html/ca.crt")
- os.chmod("/usr/share/ipa/html/ca.crt", 0444)
+ if self.self_signed_ca:
+ ca_db = certs.CertDB(dsinstance.config_dirname(dsinstance.realm_to_serverid(self.realm)))
+ else:
+ ca_db = certs.CertDB(NSS_DIR)
+ db = certs.CertDB(NSS_DIR)
tmpdir = tempfile.mkdtemp(prefix = "tmp-")
shutil.copy("/usr/share/ipa/html/preferences.html", tmpdir)
- ca.run_signtool(["-k", "Signing-Cert",
+ db.run_signtool(["-k", "Signing-Cert",
"-Z", "/usr/share/ipa/html/configure.jar",
"-e", ".html",
tmpdir])
shutil.rmtree(tmpdir)
+ def __publish_ca_cert(self):
+ if self.self_signed_ca:
+ ca_db = certs.CertDB(dsinstance.config_dirname(dsinstance.realm_to_serverid(self.realm)))
+ else:
+ ca_db = certs.CertDB(NSS_DIR)
+ shutil.copy(ca_db.cacert_fname, "/usr/share/ipa/html/ca.crt")
+ os.chmod("/usr/share/ipa/html/ca.crt", 0444)
+
def uninstall(self):
running = self.restore_state("running")
enabled = self.restore_state("enabled")