mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Implement an installer for the Dogtag certificate system.
The CA is currently not automatically installed. You have to pass in the --ca flag to install it. What works: - installation - unistallation - cert/ra plugins can issue and retrieve server certs What doesn't work: - self-signed CA is still created and issues Apache and DS certs - dogtag and python-nss not in rpm requires - requires that CS be in the "pre" install state from pkicreate
This commit is contained in:
parent
a6294ba041
commit
484eff1016
@ -69,6 +69,8 @@ def parse_options():
|
|||||||
help="admin user kerberos password")
|
help="admin user kerberos password")
|
||||||
parser.add_option("-d", "--debug", dest="debug", action="store_true",
|
parser.add_option("-d", "--debug", dest="debug", action="store_true",
|
||||||
default=False, help="print debugging information")
|
default=False, help="print debugging information")
|
||||||
|
parser.add_option("", "--ca", dest="ca", action="store_true",
|
||||||
|
default=False, help="Configure a CA instance")
|
||||||
parser.add_option("--hostname", dest="host_name", help="fully qualified name of server")
|
parser.add_option("--hostname", dest="host_name", help="fully qualified name of server")
|
||||||
parser.add_option("--ip-address", dest="ip_address", help="Master Server IP Address")
|
parser.add_option("--ip-address", dest="ip_address", help="Master Server IP Address")
|
||||||
parser.add_option("--setup-bind", dest="setup_bind", action="store_true",
|
parser.add_option("--setup-bind", dest="setup_bind", action="store_true",
|
||||||
@ -298,7 +300,7 @@ def check_dirsrv(unattended):
|
|||||||
print "\t636"
|
print "\t636"
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def uninstall():
|
def uninstall(ca = False):
|
||||||
try:
|
try:
|
||||||
run(["/usr/sbin/ipa-client-install", "--on-master", "--unattended", "--uninstall"])
|
run(["/usr/sbin/ipa-client-install", "--on-master", "--unattended", "--uninstall"])
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
@ -307,6 +309,14 @@ def uninstall():
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
ntpinstance.NTPInstance(fstore).uninstall()
|
ntpinstance.NTPInstance(fstore).uninstall()
|
||||||
|
if ca:
|
||||||
|
try:
|
||||||
|
from ipaserver.install import cainstance
|
||||||
|
except ImportError:
|
||||||
|
print >> sys.stderr, "Import failed: %s" % sys.exc_value
|
||||||
|
sys.exit(1)
|
||||||
|
cainstance.CADSInstance().uninstall()
|
||||||
|
cainstance.CAInstance().uninstall()
|
||||||
bindinstance.BindInstance(fstore).uninstall()
|
bindinstance.BindInstance(fstore).uninstall()
|
||||||
httpinstance.HTTPInstance(fstore).uninstall()
|
httpinstance.HTTPInstance(fstore).uninstall()
|
||||||
krbinstance.KrbInstance(fstore).uninstall()
|
krbinstance.KrbInstance(fstore).uninstall()
|
||||||
@ -345,7 +355,7 @@ def main():
|
|||||||
print "Aborting uninstall operation."
|
print "Aborting uninstall operation."
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
return uninstall()
|
return uninstall(options.ca)
|
||||||
|
|
||||||
print "=============================================================================="
|
print "=============================================================================="
|
||||||
print "This program will setup the FreeIPA Server."
|
print "This program will setup the FreeIPA Server."
|
||||||
@ -495,11 +505,25 @@ def main():
|
|||||||
os.write(pw_fd, options.dirsrv_pin)
|
os.write(pw_fd, options.dirsrv_pin)
|
||||||
os.close(pw_fd)
|
os.close(pw_fd)
|
||||||
|
|
||||||
|
if options.ca:
|
||||||
|
try:
|
||||||
|
from ipaserver.install import cainstance
|
||||||
|
except ImportError:
|
||||||
|
print >> sys.stderr, "Import failed: %s" % sys.exc_value
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
cs = cainstance.CADSInstance()
|
||||||
|
cs.create_instance("dirsrv", realm_name, host_name, domain_name, dm_password)
|
||||||
|
ca = cainstance.CAInstance()
|
||||||
|
ca.configure_instance("pkiuser", host_name, dm_password, dm_password)
|
||||||
|
|
||||||
# Create a directory server instance
|
# Create a directory server instance
|
||||||
ds = dsinstance.DsInstance()
|
ds = dsinstance.DsInstance()
|
||||||
if options.dirsrv_pkcs12:
|
if options.dirsrv_pkcs12:
|
||||||
pkcs12_info = (options.dirsrv_pkcs12, pw_name)
|
pkcs12_info = (options.dirsrv_pkcs12, pw_name)
|
||||||
|
try:
|
||||||
ds.create_instance(ds_user, realm_name, host_name, domain_name, dm_password, pkcs12_info)
|
ds.create_instance(ds_user, realm_name, host_name, domain_name, dm_password, pkcs12_info)
|
||||||
|
finally:
|
||||||
os.remove(pw_name)
|
os.remove(pw_name)
|
||||||
else:
|
else:
|
||||||
ds.create_instance(ds_user, realm_name, host_name, domain_name, dm_password)
|
ds.create_instance(ds_user, realm_name, host_name, domain_name, dm_password)
|
||||||
@ -540,6 +564,8 @@ def main():
|
|||||||
fd.write("realm=" + realm_name + "\n")
|
fd.write("realm=" + realm_name + "\n")
|
||||||
fd.write("domain=" + domain_name + "\n")
|
fd.write("domain=" + domain_name + "\n")
|
||||||
fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % host_name)
|
fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % host_name)
|
||||||
|
if options.ca:
|
||||||
|
fd.write("enable_ra=True\n")
|
||||||
fd.close()
|
fd.close()
|
||||||
|
|
||||||
bind = bindinstance.BindInstance(fstore)
|
bind = bindinstance.BindInstance(fstore)
|
||||||
|
@ -37,6 +37,7 @@ import backend
|
|||||||
import plugable
|
import plugable
|
||||||
import util
|
import util
|
||||||
from errors2 import PublicError, CommandError, HelpError, InternalError
|
from errors2 import PublicError, CommandError, HelpError, InternalError
|
||||||
|
import errors
|
||||||
from constants import CLI_TAB
|
from constants import CLI_TAB
|
||||||
from parameters import Password, Bytes
|
from parameters import Password, Bytes
|
||||||
from request import ugettext as _
|
from request import ugettext as _
|
||||||
|
150
ipapython/nsslib.py
Normal file
150
ipapython/nsslib.py
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
# Authors: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
#
|
||||||
|
# Copyright (C) 2009 Red Hat
|
||||||
|
# see file 'COPYING' for use and warranty information
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; version 2 only
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
#
|
||||||
|
|
||||||
|
import httplib
|
||||||
|
import getpass
|
||||||
|
import socket
|
||||||
|
import errno
|
||||||
|
|
||||||
|
from nss.error import NSPRError
|
||||||
|
import nss.io as io
|
||||||
|
import nss.nss as nss
|
||||||
|
import nss.ssl as ssl
|
||||||
|
|
||||||
|
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:
|
||||||
|
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:
|
||||||
|
return False
|
||||||
|
return False
|
||||||
|
|
||||||
|
class SSLFile(httplib.SSLFile):
|
||||||
|
"""
|
||||||
|
Override the _read method so we can use the NSS recv method.
|
||||||
|
"""
|
||||||
|
def _read(self):
|
||||||
|
buf = ''
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
buf = self._ssl.recv(self._bufsize)
|
||||||
|
except NSPRError, e:
|
||||||
|
raise e
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
return buf
|
||||||
|
|
||||||
|
class NSSFakeSocket(httplib.FakeSocket):
|
||||||
|
def makefile(self, mode, bufsize=None):
|
||||||
|
if mode != 'r' and mode != 'rb':
|
||||||
|
raise httplib.UnimplementedFileMode()
|
||||||
|
return SSLFile(self._shared, self._ssl, bufsize)
|
||||||
|
|
||||||
|
def send(self, stuff, flags = 0):
|
||||||
|
return self._ssl.send(stuff)
|
||||||
|
|
||||||
|
sendall = send
|
||||||
|
|
||||||
|
class NSSConnection(httplib.HTTPConnection):
|
||||||
|
default_port = httplib.HTTPSConnection.default_port
|
||||||
|
|
||||||
|
def __init__(self, host, port=None, key_file=None, cert_file=None,
|
||||||
|
ca_file='/etc/pki/tls/certs/ca-bundle.crt', strict=None,
|
||||||
|
dbdir=None):
|
||||||
|
httplib.HTTPConnection.__init__(self, host, port, strict)
|
||||||
|
self.key_file = key_file
|
||||||
|
self.cert_file = cert_file
|
||||||
|
self.ca_file = ca_file
|
||||||
|
|
||||||
|
if not dbdir:
|
||||||
|
raise RuntimeError("dbdir is required")
|
||||||
|
|
||||||
|
ssl.nssinit(dbdir)
|
||||||
|
ssl.set_domestic_policy()
|
||||||
|
nss.set_password_callback(self.password_callback)
|
||||||
|
|
||||||
|
# Create the socket here so we can do things like let the caller
|
||||||
|
# override the NSS callbacks
|
||||||
|
self.sslsock = ssl.SSLSocket()
|
||||||
|
self.sslsock.set_ssl_option(ssl.SSL_SECURITY, True)
|
||||||
|
self.sslsock.set_ssl_option(ssl.SSL_HANDSHAKE_AS_CLIENT, True)
|
||||||
|
self.sslsock.set_handshake_callback(self.handshake_callback)
|
||||||
|
|
||||||
|
def password_callback(self, slot, retry, password):
|
||||||
|
if not retry and password: return password
|
||||||
|
return getpass.getpass("Enter password for %s: " % slot.token_name);
|
||||||
|
|
||||||
|
def handshake_callback(self, sock):
|
||||||
|
"""
|
||||||
|
Verify callback. If we get here then the certificate is ok.
|
||||||
|
"""
|
||||||
|
if self.debuglevel > 0:
|
||||||
|
print "handshake complete, peer = %s" % (sock.get_peer_name())
|
||||||
|
pass
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
self.sslsock.set_hostname(self.host)
|
||||||
|
|
||||||
|
net_addr = io.NetworkAddress(self.host, self.port)
|
||||||
|
|
||||||
|
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
self.sslsock.connect(net_addr)
|
||||||
|
self.sock = NSSFakeSocket(sock, self.sslsock)
|
||||||
|
|
||||||
|
class NSSHTTPS(httplib.HTTP):
|
||||||
|
_connection_class = NSSConnection
|
||||||
|
|
||||||
|
def __init__(self, host='', port=None, key_file=None, cert_file=None,
|
||||||
|
ca_file='/etc/pki/tls/certs/ca-bundle.crt', strict=None):
|
||||||
|
# provide a default host, pass the X509 cert info
|
||||||
|
|
||||||
|
# urf. compensate for bad input.
|
||||||
|
if port == 0:
|
||||||
|
port = None
|
||||||
|
self._setup(self._connection_class(host, port, key_file,
|
||||||
|
cert_file, ca_file, strict))
|
||||||
|
# we never actually use these for anything, but we keep them
|
||||||
|
# here for compatibility with post-1.5.2 CVS.
|
||||||
|
self.key_file = key_file
|
||||||
|
self.cert_file = cert_file
|
||||||
|
self.ca_file = ca_file
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
h = NSSConnection("www.verisign.com", 443, dbdir="/etc/pki/nssdb")
|
||||||
|
h.set_debuglevel(1)
|
||||||
|
h.request("GET", "/")
|
||||||
|
res = h.getresponse()
|
||||||
|
print res.status
|
||||||
|
data = res.read()
|
||||||
|
print data
|
||||||
|
h.close()
|
@ -4,6 +4,7 @@ appdir = $(pythondir)/ipaserver
|
|||||||
app_PYTHON = \
|
app_PYTHON = \
|
||||||
__init__.py \
|
__init__.py \
|
||||||
bindinstance.py \
|
bindinstance.py \
|
||||||
|
cainstance.py \
|
||||||
dsinstance.py \
|
dsinstance.py \
|
||||||
ipaldap.py \
|
ipaldap.py \
|
||||||
krbinstance.py \
|
krbinstance.py \
|
||||||
|
743
ipaserver/install/cainstance.py
Normal file
743
ipaserver/install/cainstance.py
Normal file
@ -0,0 +1,743 @@
|
|||||||
|
# Authors: Rob Crittenden <rcritten@redhat.com>
|
||||||
|
# Ade Lee <alee@redhat.com>
|
||||||
|
# Andrew Wnuk <awnuk@redhat.com>
|
||||||
|
#
|
||||||
|
# Copyright (C) 2009 Red Hat
|
||||||
|
# see file 'COPYING' for use and warranty information
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation; version 2 only
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
#
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import pwd
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
import ldap
|
||||||
|
import base64
|
||||||
|
import array
|
||||||
|
import tempfile
|
||||||
|
import binascii
|
||||||
|
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
|
||||||
|
|
||||||
|
from ipapython import ipautil
|
||||||
|
from ipapython import nsslib
|
||||||
|
|
||||||
|
from ipaserver.install import service
|
||||||
|
from ipaserver.install import installutils
|
||||||
|
from ipaserver import ipaldap
|
||||||
|
from ipaserver.install import ldapupdate
|
||||||
|
from ipaserver.install import dsinstance
|
||||||
|
from ipalib import util
|
||||||
|
|
||||||
|
DEFAULT_DSPORT=7389
|
||||||
|
|
||||||
|
# We need to reset the template because the CA uses the regular boot
|
||||||
|
# information
|
||||||
|
INF_TEMPLATE = """
|
||||||
|
[General]
|
||||||
|
FullMachineName= $FQHN
|
||||||
|
SuiteSpotUserID= $USER
|
||||||
|
ServerRoot= $SERVER_ROOT
|
||||||
|
[slapd]
|
||||||
|
ServerPort= $DSPORT
|
||||||
|
ServerIdentifier= $SERVERID
|
||||||
|
Suffix= $SUFFIX
|
||||||
|
RootDN= cn=Directory Manager
|
||||||
|
RootDNPwd= $PASSWORD
|
||||||
|
"""
|
||||||
|
|
||||||
|
def get_preop_pin(instance_root, instance_name):
|
||||||
|
preop_pin = None
|
||||||
|
|
||||||
|
filename = instance_root + "/" + instance_name + "/conf/CS.cfg"
|
||||||
|
|
||||||
|
# read the config file and get the preop pin
|
||||||
|
try:
|
||||||
|
f=open(filename)
|
||||||
|
except IOError, e:
|
||||||
|
logging.error("Cannot open configuration file." + str(e))
|
||||||
|
raise e
|
||||||
|
data = f.read()
|
||||||
|
data = data.split('\n')
|
||||||
|
pattern = re.compile("preop.pin=(.*)" )
|
||||||
|
for line in data:
|
||||||
|
match = re.search(pattern, line)
|
||||||
|
if (match):
|
||||||
|
preop_pin=match.group(1)
|
||||||
|
break
|
||||||
|
|
||||||
|
return preop_pin
|
||||||
|
|
||||||
|
def export_pkcs12(output_file, output_passwd, nickname, cert_database,
|
||||||
|
cert_passwd):
|
||||||
|
ipautil.run(["/usr/bin/pk12util", "-d", cert_database,
|
||||||
|
"-o", output_file,
|
||||||
|
"-n", nickname,
|
||||||
|
"-k", cert_passwd,
|
||||||
|
"-w", output_passwd])
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
def get_value(s):
|
||||||
|
"""
|
||||||
|
Parse out a name/value pair from a Javascript variable.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
expr = s.split('=',1)
|
||||||
|
value = expr[1]
|
||||||
|
value = value.replace('\"', '')
|
||||||
|
value = value.replace(';','')
|
||||||
|
value = value.replace('\\n','\n')
|
||||||
|
value = value.replace('\\r','\r')
|
||||||
|
return value
|
||||||
|
except IndexError:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def find_substring(data, value):
|
||||||
|
"""
|
||||||
|
Scan through a list looking for a string that starts with value.
|
||||||
|
"""
|
||||||
|
for d in data:
|
||||||
|
if d.startswith(value):
|
||||||
|
return get_value(d)
|
||||||
|
|
||||||
|
def get_defList(data):
|
||||||
|
"""
|
||||||
|
Return a dictionary of defList name/value pairs.
|
||||||
|
|
||||||
|
A certificate signing request is specfied as a series of these.
|
||||||
|
"""
|
||||||
|
varname = None
|
||||||
|
value = None
|
||||||
|
skip = False
|
||||||
|
defdict = {}
|
||||||
|
for d in data:
|
||||||
|
if d.startswith("defList = new Object"):
|
||||||
|
varname = None
|
||||||
|
value = None
|
||||||
|
skip = False
|
||||||
|
if d.startswith("defList.defId"):
|
||||||
|
varname = get_value(d)
|
||||||
|
if d.startswith("defList.defVal"):
|
||||||
|
value = get_value(d)
|
||||||
|
if skip:
|
||||||
|
varname = None
|
||||||
|
value = None
|
||||||
|
skip = False
|
||||||
|
if d.startswith("defList.defConstraint"):
|
||||||
|
ctype = get_value(d)
|
||||||
|
if ctype == "readonly":
|
||||||
|
skip = True
|
||||||
|
|
||||||
|
if varname and value:
|
||||||
|
defdict[varname] = value
|
||||||
|
varname = None
|
||||||
|
value = None
|
||||||
|
|
||||||
|
return defdict
|
||||||
|
|
||||||
|
def get_outputList(data):
|
||||||
|
"""
|
||||||
|
Return a dictionary of outputList name/value pairs.
|
||||||
|
|
||||||
|
The output from issuing a certificate is a series of these.
|
||||||
|
"""
|
||||||
|
varname = None
|
||||||
|
value = None
|
||||||
|
outputdict = {}
|
||||||
|
for d in data:
|
||||||
|
if d.startswith("outputList = new"):
|
||||||
|
varname = None
|
||||||
|
value = None
|
||||||
|
if d.startswith("outputList.outputId"):
|
||||||
|
varname = get_value(d)
|
||||||
|
if d.startswith("outputList.outputVal"):
|
||||||
|
value = get_value(d)
|
||||||
|
|
||||||
|
if varname and value:
|
||||||
|
outputdict[varname] = value
|
||||||
|
varname = None
|
||||||
|
value = None
|
||||||
|
|
||||||
|
return outputdict
|
||||||
|
|
||||||
|
class CADSInstance(service.Service):
|
||||||
|
def __init__(self, realm_name=None, domain_name=None, dm_password=None):
|
||||||
|
service.Service.__init__(self, "pkids")
|
||||||
|
self.realm_name = realm_name
|
||||||
|
self.dm_password = dm_password
|
||||||
|
self.sub_dict = None
|
||||||
|
self.domain = domain_name
|
||||||
|
self.serverid = None
|
||||||
|
self.host_name = None
|
||||||
|
self.pkcs12_info = None
|
||||||
|
self.ds_user = None
|
||||||
|
self.ds_port = None
|
||||||
|
if realm_name:
|
||||||
|
self.suffix = util.realm_to_suffix(self.realm_name)
|
||||||
|
self.__setup_sub_dict()
|
||||||
|
else:
|
||||||
|
self.suffix = None
|
||||||
|
|
||||||
|
def create_instance(self, ds_user, realm_name, host_name, domain_name, dm_password, pkcs12_info=None, ds_port=DEFAULT_DSPORT):
|
||||||
|
self.ds_user = ds_user
|
||||||
|
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.dm_password = dm_password
|
||||||
|
self.domain = domain_name
|
||||||
|
self.pkcs12_info = pkcs12_info
|
||||||
|
self.__setup_sub_dict()
|
||||||
|
|
||||||
|
self.step("creating directory server user", self.__create_ds_user)
|
||||||
|
self.step("creating directory server instance", self.__create_instance)
|
||||||
|
self.step("configuring directory to start on boot", self.__enable)
|
||||||
|
self.step("restarting directory server", self.__restart_instance)
|
||||||
|
|
||||||
|
self.start_creation("Configuring directory server for the CA:")
|
||||||
|
|
||||||
|
def __setup_sub_dict(self):
|
||||||
|
server_root = dsinstance.find_server_root()
|
||||||
|
self.sub_dict = dict(FQHN=self.host_name, SERVERID=self.serverid,
|
||||||
|
PASSWORD=self.dm_password, SUFFIX=self.suffix.lower(),
|
||||||
|
REALM=self.realm_name, USER=self.ds_user,
|
||||||
|
SERVER_ROOT=server_root, DOMAIN=self.domain,
|
||||||
|
TIME=int(time.time()), DSPORT=self.ds_port)
|
||||||
|
|
||||||
|
def __enable(self):
|
||||||
|
name = self.service_name
|
||||||
|
self.service_name="dirsrv"
|
||||||
|
self.backup_state("enabled", self.is_enabled())
|
||||||
|
self.chkconfig_on()
|
||||||
|
self.service_name = name
|
||||||
|
|
||||||
|
def __create_ds_user(self):
|
||||||
|
user_exists = True
|
||||||
|
try:
|
||||||
|
pwd.getpwnam(self.ds_user)
|
||||||
|
logging.debug("ds user %s exists" % self.ds_user)
|
||||||
|
except KeyError:
|
||||||
|
user_exists = False
|
||||||
|
logging.debug("adding ds user %s" % self.ds_user)
|
||||||
|
args = ["/usr/sbin/useradd", "-c", "DS System User", "-d", "/var/lib/dirsrv", "-M", "-r", "-s", "/sbin/nologin", self.ds_user]
|
||||||
|
try:
|
||||||
|
ipautil.run(args)
|
||||||
|
logging.debug("done adding user")
|
||||||
|
except ipautil.CalledProcessError, e:
|
||||||
|
logging.critical("failed to add user %s" % e)
|
||||||
|
|
||||||
|
self.backup_state("user", self.ds_user)
|
||||||
|
self.backup_state("user_exists", user_exists)
|
||||||
|
|
||||||
|
def __create_instance(self):
|
||||||
|
self.backup_state("running", dsinstance.is_ds_running())
|
||||||
|
self.backup_state("serverid", self.serverid)
|
||||||
|
|
||||||
|
inf_txt = ipautil.template_str(INF_TEMPLATE, self.sub_dict)
|
||||||
|
logging.debug("writing inf template")
|
||||||
|
inf_fd = ipautil.write_tmp_file(inf_txt)
|
||||||
|
inf_txt = re.sub(r"RootDNPwd=.*\n", "", inf_txt)
|
||||||
|
logging.debug(inf_txt)
|
||||||
|
if ipautil.file_exists("/usr/sbin/setup-ds.pl"):
|
||||||
|
args = ["/usr/sbin/setup-ds.pl", "--silent", "--logfile", "-", "-f", inf_fd.name]
|
||||||
|
logging.debug("calling setup-ds.pl")
|
||||||
|
else:
|
||||||
|
args = ["/usr/bin/ds_newinst.pl", inf_fd.name]
|
||||||
|
logging.debug("calling ds_newinst.pl")
|
||||||
|
try:
|
||||||
|
ipautil.run(args)
|
||||||
|
logging.debug("completed creating ds instance")
|
||||||
|
except ipautil.CalledProcessError, e:
|
||||||
|
logging.critical("failed to restart ds instance %s" % e)
|
||||||
|
inf_fd.close()
|
||||||
|
|
||||||
|
def __restart_instance(self):
|
||||||
|
try:
|
||||||
|
# Have to trick the base class to use the right service name
|
||||||
|
sav_name = self.service_name
|
||||||
|
self.service_name="dirsrv"
|
||||||
|
self.restart(self.serverid)
|
||||||
|
self.service_name=sav_name
|
||||||
|
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:
|
||||||
|
# TODO: roll back here?
|
||||||
|
logging.critical("Failed to restart the directory server. See the installation log for details.")
|
||||||
|
|
||||||
|
def uninstall(self):
|
||||||
|
running = self.restore_state("running")
|
||||||
|
enabled = self.restore_state("enabled")
|
||||||
|
serverid = self.restore_state("serverid")
|
||||||
|
sav_name = self.service_name
|
||||||
|
self.service_name="dirsrv"
|
||||||
|
|
||||||
|
if not running is None:
|
||||||
|
self.stop(serverid)
|
||||||
|
|
||||||
|
if not enabled is None and not enabled:
|
||||||
|
self.chkconfig_off()
|
||||||
|
|
||||||
|
if not serverid is None:
|
||||||
|
dsinstance.erase_ds_instance_data(serverid)
|
||||||
|
|
||||||
|
ds_user = self.restore_state("user")
|
||||||
|
user_exists = self.restore_state("user_exists")
|
||||||
|
|
||||||
|
if not ds_user is None and not user_exists is None and not user_exists:
|
||||||
|
try:
|
||||||
|
ipautil.run(["/usr/sbin/userdel", ds_user])
|
||||||
|
except ipautil.CalledProcessError, e:
|
||||||
|
logging.critical("failed to delete user %s" % e)
|
||||||
|
self.service_name = sav_name
|
||||||
|
|
||||||
|
|
||||||
|
class CAInstance(service.Service):
|
||||||
|
def __init__(self):
|
||||||
|
service.Service.__init__(self, "pki-ca")
|
||||||
|
self.pki_user = None
|
||||||
|
self.dm_password = None
|
||||||
|
self.admin_password = None
|
||||||
|
self.host_name = None
|
||||||
|
|
||||||
|
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.ds_port = DEFAULT_DSPORT
|
||||||
|
self.domain_name = "IPA"
|
||||||
|
self.server_root = "/var/lib"
|
||||||
|
self.secure_port = 9444
|
||||||
|
self.ra_cert = None
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
shutil.rmtree(self.ca_agent_db, ignore_errors=True)
|
||||||
|
|
||||||
|
def configure_instance(self, pki_user, host_name, dm_password, admin_password, ds_port=DEFAULT_DSPORT):
|
||||||
|
self.pki_user = pki_user
|
||||||
|
self.host_name = host_name
|
||||||
|
self.dm_password = dm_password
|
||||||
|
self.admin_password = admin_password
|
||||||
|
self.ds_port = ds_port
|
||||||
|
|
||||||
|
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)
|
||||||
|
self.step("creating RA agent certificate database", self.__create_ra_agent_db)
|
||||||
|
self.step("importing CA chain to RA certificate database", self.__import_ca_chain)
|
||||||
|
self.step("requesting RA certificate from CA", self.__request_ra_certificate)
|
||||||
|
self.step("issuing RA agent certificate", self.__issue_ra_cert)
|
||||||
|
self.step("adding RA agent as a trusted user", self.__configure_ra)
|
||||||
|
self.step("fixing RA database permissions", self.__fix_ra_perms)
|
||||||
|
self.step("configuring certificate server to start on boot", self.__enable)
|
||||||
|
self.step("restarting certificate server", self.__restart_instance)
|
||||||
|
|
||||||
|
self.start_creation("Configuring certificate server:")
|
||||||
|
|
||||||
|
def __enable(self):
|
||||||
|
self.backup_state("enabled", self.is_enabled())
|
||||||
|
self.chkconfig_on()
|
||||||
|
|
||||||
|
def __create_ca_user(self):
|
||||||
|
user_exists = True
|
||||||
|
try:
|
||||||
|
pwd.getpwnam(self.pki_user)
|
||||||
|
logging.debug("ca user %s exists" % self.pki_user)
|
||||||
|
except KeyError:
|
||||||
|
user_exists = False
|
||||||
|
logging.debug("adding ca user %s" % self.pki_user)
|
||||||
|
args = ["/usr/sbin/useradd", "-c", "CA System User", "-d", "/var/lib", "-M", "-r", "-s", "/sbin/nologin", self.pki_user]
|
||||||
|
try:
|
||||||
|
ipautil.run(args)
|
||||||
|
logging.debug("done adding user")
|
||||||
|
except ipautil.CalledProcessError, e:
|
||||||
|
logging.critical("failed to add user %s" % e)
|
||||||
|
|
||||||
|
self.backup_state("user", self.pki_user)
|
||||||
|
self.backup_state("user_exists", user_exists)
|
||||||
|
|
||||||
|
def __configure_instance(self):
|
||||||
|
#--skipcreate -u pkiuser -g pkiuser -p password -a password -d --hostname `hostname` -n IPA
|
||||||
|
|
||||||
|
preop_pin = get_preop_pin(self.server_root, self.service_name)
|
||||||
|
|
||||||
|
try:
|
||||||
|
args = ["/usr/bin/perl", "/usr/bin/pkisilent", "ConfigureCA",
|
||||||
|
"-cs_hostname", self.host_name,
|
||||||
|
"-cs_port", str(self.secure_port),
|
||||||
|
"-client_certdb_dir", self.ca_agent_db,
|
||||||
|
"-client_certdb_pwd", self.admin_password,
|
||||||
|
"-preop_pin" , preop_pin,
|
||||||
|
"-domain_name", self.domain_name,
|
||||||
|
"-admin_user", "admin",
|
||||||
|
"-admin_email", "root@localhost",
|
||||||
|
"-admin_password", self.admin_password,
|
||||||
|
"-agent_name", "ipa-ca-agent",
|
||||||
|
"-agent_key_size", "2048",
|
||||||
|
"-agent_key_type", "rsa",
|
||||||
|
"-agent_cert_subject", "\"CN=ipa-ca-agent,O=" + self.domain_name + "\"",
|
||||||
|
"-ldap_host", self.host_name,
|
||||||
|
"-ldap_port", str(self.ds_port),
|
||||||
|
"-bind_dn", "\"cn=Directory Manager\"",
|
||||||
|
"-bind_password", self.dm_password,
|
||||||
|
"-base_dn", self.basedn,
|
||||||
|
"-db_name", "ipaca",
|
||||||
|
"-key_size", "2048",
|
||||||
|
"-key_type", "rsa",
|
||||||
|
"-save_p12", "true",
|
||||||
|
"-backup_pwd", self.admin_password,
|
||||||
|
"-subsystem_name", self.service_name,
|
||||||
|
"-token_name", "internal",
|
||||||
|
"-ca_subsystem_cert_subject_name", "\"CN=CA Subsystem Certificate,O=" + self.domain_name + "\"",
|
||||||
|
"-ca_ocsp_cert_subject_name", "\"CN=OCSP Signing Certificate,O=" + self.domain_name + "\"",
|
||||||
|
"-ca_server_cert_subject_name", "CN=" + self.host_name + ",O=" + self.domain_name,
|
||||||
|
"-ca_audit_signing_cert_subject_name", "\"CN=CA Audit Signing Certificate,O=" + self.domain_name + "\"",
|
||||||
|
"-ca_sign_cert_subject_name", "\"CN=Certificate Authority,O=" + self.domain_name + "\"" ]
|
||||||
|
# if (options.external):
|
||||||
|
# pass
|
||||||
|
# args.append("-external")
|
||||||
|
# args.append("true")
|
||||||
|
# args.append("-ext_csr_file")
|
||||||
|
# args.append(ext_csr_file)
|
||||||
|
# if (options.cacertfile):
|
||||||
|
# args.append("-ext_ca_cert_file")
|
||||||
|
# args.append(options.cacertfile)
|
||||||
|
# if (options.cacertchainfile):
|
||||||
|
# args.append("-ext_ca_cert_chain_file")
|
||||||
|
# args.append(options.cacertchainfile)
|
||||||
|
# else:
|
||||||
|
# args.append("-external")
|
||||||
|
# args.append("false")
|
||||||
|
# if (options.clone):
|
||||||
|
# pass
|
||||||
|
# args.append("-clone")
|
||||||
|
# args.append("true")
|
||||||
|
# args.append("-clone_p12_file")
|
||||||
|
# args.append(options.clonefile)
|
||||||
|
# args.append("-clone_p12_password")
|
||||||
|
# args.append(options.clonepasswd)
|
||||||
|
# args.append("-clone_uri")
|
||||||
|
# args.append(options.cloneURI)
|
||||||
|
# args.append("-sd_hostname")
|
||||||
|
# args.append(options.sd_hostname)
|
||||||
|
# args.append("-sd_ssl_port")
|
||||||
|
# args.append(options.sd_ssl_port)
|
||||||
|
# args.append("-sd_admin_name")
|
||||||
|
# args.append(options.sd_admin_name)
|
||||||
|
# args.append("-sd_admin_password")
|
||||||
|
# args.append(options.sd_admin_password)
|
||||||
|
# else:
|
||||||
|
# args.append("-clone")
|
||||||
|
# args.append("false")
|
||||||
|
|
||||||
|
# FIXME
|
||||||
|
args.append("-external")
|
||||||
|
args.append("false")
|
||||||
|
args.append("-clone")
|
||||||
|
args.append("false")
|
||||||
|
|
||||||
|
logging.debug(args)
|
||||||
|
ipautil.run(args)
|
||||||
|
logging.debug("completed creating ca instance")
|
||||||
|
except ipautil.CalledProcessError, e:
|
||||||
|
logging.critical("failed to restart ca instance %s" % e)
|
||||||
|
logging.debug("restarting ca instance")
|
||||||
|
try:
|
||||||
|
self.restart()
|
||||||
|
logging.debug("done restarting ca instance")
|
||||||
|
except ipautil.CalledProcessError, e:
|
||||||
|
print "failed to restart ca instance", e
|
||||||
|
logging.debug("failed to restart ca instance %s" % e)
|
||||||
|
|
||||||
|
def __restart_instance(self):
|
||||||
|
try:
|
||||||
|
self.restart()
|
||||||
|
except Exception, e:
|
||||||
|
# TODO: roll back here?
|
||||||
|
logging.critical("Failed to restart the certificate server. See the installation log for details.")
|
||||||
|
|
||||||
|
def __get_agent_cert(self, nickname):
|
||||||
|
args = ["/usr/bin/certutil", "-L", "-d", self.ca_agent_db, "-n", nickname, "-a"]
|
||||||
|
(out, err) = ipautil.run(args)
|
||||||
|
out = out.replace('-----BEGIN CERTIFICATE-----', '')
|
||||||
|
out = out.replace('-----END CERTIFICATE-----', '')
|
||||||
|
return out
|
||||||
|
|
||||||
|
def __issue_ra_cert(self):
|
||||||
|
# The CA certificate is in the agent DB but isn't trusted
|
||||||
|
(admin_fd, admin_name) = tempfile.mkstemp()
|
||||||
|
os.write(admin_fd, self.admin_password)
|
||||||
|
os.close(admin_fd)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.__run_certutil(
|
||||||
|
['-M', '-t', 'CT,C,C', '-n',
|
||||||
|
'Certificate Authority - %s' % self.domain_name
|
||||||
|
], database=self.ca_agent_db, pwd_file=self.admin_password)
|
||||||
|
finally:
|
||||||
|
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')
|
||||||
|
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')
|
||||||
|
outputList = get_outputList(data)
|
||||||
|
|
||||||
|
self.ra_cert = outputList['b64_cert']
|
||||||
|
self.ra_cert = self.ra_cert.replace('\\n','')
|
||||||
|
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
|
||||||
|
(agent_fd, agent_name) = tempfile.mkstemp()
|
||||||
|
os.write(agent_fd, self.ra_cert)
|
||||||
|
os.close(agent_fd)
|
||||||
|
try:
|
||||||
|
self.__run_certutil(
|
||||||
|
['-A', '-t', 'u,u,u', '-n', 'ipaCert', '-a',
|
||||||
|
'-i', agent_name]
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
os.remove(agent_name)
|
||||||
|
|
||||||
|
def __configure_ra(self):
|
||||||
|
# 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.protocol_version=ldap.VERSION3
|
||||||
|
ld.simple_bind_s("cn=Directory Manager", self.dm_password)
|
||||||
|
|
||||||
|
decoded = base64.b64decode(self.ra_cert)
|
||||||
|
|
||||||
|
entry_dn = "uid=%s,ou=People,%s" % ("ipara", self.basedn)
|
||||||
|
entry = [
|
||||||
|
('objectClass', ['top', 'person', 'organizationalPerson', 'inetOrgPerson', 'cmsuser']),
|
||||||
|
('uid', "ipara"),
|
||||||
|
('sn', "ipara"),
|
||||||
|
('cn', "ipara"),
|
||||||
|
('usertype', "agentType"),
|
||||||
|
('userstate', "1"),
|
||||||
|
('userCertificate;binary', decoded),
|
||||||
|
('description', '2;7;CN=Certificate Authority,O=%s;CN=RA Subsystem Certificate,OU=pki-ipa,O=%s' % (self.domain_name, self.domain_name)),]
|
||||||
|
|
||||||
|
ld.add_s(entry_dn, entry)
|
||||||
|
|
||||||
|
dn = "cn=Certificate Manager Agents,ou=groups,%s" % self.basedn
|
||||||
|
modlist = [(0, 'uniqueMember', '%s' % entry_dn)]
|
||||||
|
ld.modify_s(dn, modlist)
|
||||||
|
|
||||||
|
dn = "cn=Registration Manager Agents,ou=groups,%s" % self.basedn
|
||||||
|
modlist = [(0, 'uniqueMember', '%s' % entry_dn)]
|
||||||
|
ld.modify_s(dn, modlist)
|
||||||
|
|
||||||
|
ld.unbind_s()
|
||||||
|
|
||||||
|
def __run_certutil(self, args, database=None, pwd_file=None,stdin=None):
|
||||||
|
if not database:
|
||||||
|
database = self.ra_agent_db
|
||||||
|
if not pwd_file:
|
||||||
|
pwd_file = self.ra_agent_pwd
|
||||||
|
new_args = ["/usr/bin/certutil", "-d", database, "-f", pwd_file]
|
||||||
|
new_args = new_args + args
|
||||||
|
return ipautil.run(new_args, stdin)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
if not ipautil.dir_exists(self.ra_agent_db):
|
||||||
|
os.mkdir(self.ra_agent_db)
|
||||||
|
|
||||||
|
# Create the password file for this db
|
||||||
|
hex_str = binascii.hexlify(os.urandom(10))
|
||||||
|
f = os.open(self.ra_agent_pwd, os.O_CREAT | os.O_RDWR)
|
||||||
|
os.write(f, hex_str)
|
||||||
|
os.close(f)
|
||||||
|
|
||||||
|
stdout, stderr = self.__run_certutil(["-N"])
|
||||||
|
|
||||||
|
def __get_ca_chain(self):
|
||||||
|
conn = httplib.HTTPConnection(self.host_name, 9180)
|
||||||
|
conn.request("GET", "/ca/ee/ca/getCertChain")
|
||||||
|
res = conn.getresponse()
|
||||||
|
if res.status == 200:
|
||||||
|
data = res.read()
|
||||||
|
|
||||||
|
doc = xml.dom.minidom.parseString(data)
|
||||||
|
item_node = doc.getElementsByTagName("ChainBase64")
|
||||||
|
chain = item_node[0].childNodes[0].data
|
||||||
|
doc.unlink()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
return chain
|
||||||
|
else:
|
||||||
|
# FIXME: raise proper exception
|
||||||
|
conn.close()
|
||||||
|
raise ValueError("Unable to retrieve CA chain")
|
||||||
|
|
||||||
|
def __create_ca_agent_pkcs12(self):
|
||||||
|
(pwd_fd, pwd_name) = tempfile.mkstemp()
|
||||||
|
os.write(pwd_fd, self.admin_password)
|
||||||
|
os.close(pwd_fd)
|
||||||
|
try:
|
||||||
|
ipautil.run(["/usr/bin/pk12util",
|
||||||
|
"-n", "ipa-ca-agent",
|
||||||
|
"-o", "/root/ca-agent.p12",
|
||||||
|
"-d", self.ca_agent_db,
|
||||||
|
"-k", pwd_name,
|
||||||
|
"-w", pwd_name])
|
||||||
|
finally:
|
||||||
|
os.remove(pwd_name)
|
||||||
|
|
||||||
|
def __import_ca_chain(self):
|
||||||
|
chain = self.__get_ca_chain()
|
||||||
|
(chain_fd, chain_name) = tempfile.mkstemp()
|
||||||
|
os.write(chain_fd, chain)
|
||||||
|
os.close(chain_fd)
|
||||||
|
try:
|
||||||
|
self.__run_certutil(
|
||||||
|
['-A', '-t', 'CT,C,C', '-n', 'caCert', '-a',
|
||||||
|
'-i', chain_name]
|
||||||
|
)
|
||||||
|
finally:
|
||||||
|
os.remove(chain_name)
|
||||||
|
|
||||||
|
def __request_ra_certificate(self):
|
||||||
|
# Create a noise file for generating our private key
|
||||||
|
noise = array.array('B', os.urandom(128))
|
||||||
|
(noise_fd, noise_name) = tempfile.mkstemp()
|
||||||
|
os.write(noise_fd, noise)
|
||||||
|
os.close(noise_fd)
|
||||||
|
|
||||||
|
# Generate our CSR. The result gets put into stdout
|
||||||
|
try:
|
||||||
|
(stdout, stderr) = self.__run_certutil(["-R", "-k", "rsa", "-g", "2048", "-s", "CN=RA Subsystem Certificate,OU=pki-ipa,O=%s" % self.domain_name, "-z", noise_name, "-a"])
|
||||||
|
finally:
|
||||||
|
os.remove(noise_name)
|
||||||
|
|
||||||
|
csr = stdout.find("-----BEGIN NEW CERTIFICATE REQUEST-----")
|
||||||
|
if csr >= 0:
|
||||||
|
csr = stdout[csr:]
|
||||||
|
|
||||||
|
# Send the request to the CA
|
||||||
|
conn = httplib.HTTPConnection(self.host_name, 9180)
|
||||||
|
params = urllib.urlencode({'profileId': 'caServerCert',
|
||||||
|
'cert_request_type': 'pkcs10',
|
||||||
|
'requestor_name': 'IPA Installer',
|
||||||
|
'cert_request': csr,
|
||||||
|
'xmlOutput': 'true'})
|
||||||
|
headers = {"Content-type": "application/x-www-form-urlencoded",
|
||||||
|
"Accept": "text/plain"}
|
||||||
|
|
||||||
|
conn.request("POST", "/ca/ee/ca/profileSubmit", params, headers)
|
||||||
|
res = conn.getresponse()
|
||||||
|
if res.status == 200:
|
||||||
|
data = res.read()
|
||||||
|
# print data
|
||||||
|
|
||||||
|
conn.close()
|
||||||
|
else:
|
||||||
|
conn.close()
|
||||||
|
# FIXME: raise proper exception
|
||||||
|
raise ValueError("Unable to submit RA cert request")
|
||||||
|
|
||||||
|
def __fix_ra_perms(self):
|
||||||
|
os.chmod(self.ra_agent_db + "/cert8.db", 0640)
|
||||||
|
os.chmod(self.ra_agent_db + "/key3.db", 0640)
|
||||||
|
os.chmod(self.ra_agent_db + "/secmod.db", 0640)
|
||||||
|
|
||||||
|
pent = pwd.getpwnam("apache")
|
||||||
|
os.chown(self.ra_agent_db + "/cert8.db", 0, pent.pw_gid )
|
||||||
|
os.chown(self.ra_agent_db + "/key3.db", 0, pent.pw_gid )
|
||||||
|
os.chown(self.ra_agent_db + "/secmod.db", 0, pent.pw_gid )
|
||||||
|
os.chown(self.ra_agent_pwd, 0, pent.pw_gid)
|
||||||
|
|
||||||
|
def uninstall(self):
|
||||||
|
try:
|
||||||
|
ipautil.run(["/usr/bin/pkiremove", "-pki_instance_root=/var/lib",
|
||||||
|
"-pki_instance_name=pki-ca", "-force"])
|
||||||
|
except ipautil.CalledProcessError, e:
|
||||||
|
logging.critical("failed to uninstall CA instance %s" % e)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
installutils.standard_logging_setup("install.log", False)
|
||||||
|
cs = CADSInstance()
|
||||||
|
cs.create_instance("dirsrv", "GREYOAK.COM", "catest.greyoak.com", "greyoak.com", "password")
|
||||||
|
ca = CAInstance()
|
||||||
|
ca.configure_instance("pkiuser", "catest.greyoak.com", "password", "password")
|
@ -248,7 +248,7 @@ class DsInstance(service.Service):
|
|||||||
logging.critical("failed to restart ds instance %s" % e)
|
logging.critical("failed to restart ds instance %s" % e)
|
||||||
logging.debug("restarting ds instance")
|
logging.debug("restarting ds instance")
|
||||||
try:
|
try:
|
||||||
self.restart()
|
self.restart(self.serverid)
|
||||||
logging.debug("done restarting ds instance")
|
logging.debug("done restarting ds instance")
|
||||||
except ipautil.CalledProcessError, e:
|
except ipautil.CalledProcessError, e:
|
||||||
print "failed to restart ds instance", e
|
print "failed to restart ds instance", e
|
||||||
@ -276,7 +276,7 @@ class DsInstance(service.Service):
|
|||||||
|
|
||||||
def __restart_instance(self):
|
def __restart_instance(self):
|
||||||
try:
|
try:
|
||||||
self.restart()
|
self.restart(self.serverid)
|
||||||
if not is_ds_running():
|
if not is_ds_running():
|
||||||
logging.critical("Failed to restart the directory server. See the installation log for details.")
|
logging.critical("Failed to restart the directory server. See the installation log for details.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
@ -22,19 +22,19 @@ from ipapython import sysrestore
|
|||||||
from ipapython import ipautil
|
from ipapython import ipautil
|
||||||
|
|
||||||
|
|
||||||
def stop(service_name):
|
def stop(service_name, instance_name=""):
|
||||||
ipautil.run(["/sbin/service", service_name, "stop"])
|
ipautil.run(["/sbin/service", service_name, "stop", instance_name])
|
||||||
|
|
||||||
def start(service_name):
|
def start(service_name, instance_name=""):
|
||||||
ipautil.run(["/sbin/service", service_name, "start"])
|
ipautil.run(["/sbin/service", service_name, "start", instance_name])
|
||||||
|
|
||||||
def restart(service_name):
|
def restart(service_name, instance_name=""):
|
||||||
ipautil.run(["/sbin/service", service_name, "restart"])
|
ipautil.run(["/sbin/service", service_name, "restart", instance_name])
|
||||||
|
|
||||||
def is_running(service_name):
|
def is_running(service_name, instance_name=""):
|
||||||
ret = True
|
ret = True
|
||||||
try:
|
try:
|
||||||
ipautil.run(["/sbin/service", service_name, "status"])
|
ipautil.run(["/sbin/service", service_name, "status", instance_name])
|
||||||
except ipautil.CalledProcessError:
|
except ipautil.CalledProcessError:
|
||||||
ret = False
|
ret = False
|
||||||
return ret
|
return ret
|
||||||
@ -91,14 +91,14 @@ class Service:
|
|||||||
def set_output(self, fd):
|
def set_output(self, fd):
|
||||||
self.output_fd = fd
|
self.output_fd = fd
|
||||||
|
|
||||||
def stop(self):
|
def stop(self, instance_name=""):
|
||||||
stop(self.service_name)
|
stop(self.service_name, instance_name)
|
||||||
|
|
||||||
def start(self):
|
def start(self, instance_name=""):
|
||||||
start(self.service_name)
|
start(self.service_name, instance_name)
|
||||||
|
|
||||||
def restart(self):
|
def restart(self, instance_name=""):
|
||||||
restart(self.service_name)
|
restart(self.service_name, instance_name)
|
||||||
|
|
||||||
def is_running(self):
|
def is_running(self):
|
||||||
return is_running(self.service_name)
|
return is_running(self.service_name)
|
||||||
|
@ -55,7 +55,10 @@ class ra(Backend):
|
|||||||
Request Authority backend plugin.
|
Request Authority backend plugin.
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
|
if api.env.home:
|
||||||
self.sec_dir = api.env.dot_ipa + os.sep + 'alias'
|
self.sec_dir = api.env.dot_ipa + os.sep + 'alias'
|
||||||
|
else:
|
||||||
|
self.sec_dir = "/etc/ipa/ra" + os.sep + 'alias'
|
||||||
self.pwd_file = self.sec_dir + os.sep + '.pwd'
|
self.pwd_file = self.sec_dir + os.sep + '.pwd'
|
||||||
self.noise_file = self.sec_dir + os.sep + '.noise'
|
self.noise_file = self.sec_dir + os.sep + '.noise'
|
||||||
self.ipa_key_size = "2048"
|
self.ipa_key_size = "2048"
|
||||||
|
Loading…
Reference in New Issue
Block a user