summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ipa-python/ipautil.py2
-rwxr-xr-xipa-server/freeipa-server.spec2
-rw-r--r--ipa-server/freeipa-server.spec.in2
-rw-r--r--ipa-server/ipa-install/Makefile.am2
-rw-r--r--ipa-server/ipa-install/ipa-replica-install142
-rw-r--r--ipa-server/ipa-install/ipa-replica-prepare114
-rw-r--r--ipa-server/ipa-install/ipa-server-install159
-rw-r--r--ipa-server/ipa-install/share/kerberos.ldif18
-rw-r--r--ipa-server/ipaserver/Makefile.am2
-rw-r--r--ipa-server/ipaserver/dsinstance.py104
-rw-r--r--ipa-server/ipaserver/installutils.py108
-rw-r--r--ipa-server/ipaserver/ipaldap.py101
-rw-r--r--ipa-server/ipaserver/krbinstance.py199
-rw-r--r--ipa-server/ipaserver/radiusinstance.py3
14 files changed, 705 insertions, 253 deletions
diff --git a/ipa-python/ipautil.py b/ipa-python/ipautil.py
index e7f59419..cd8eac16 100644
--- a/ipa-python/ipautil.py
+++ b/ipa-python/ipautil.py
@@ -25,6 +25,7 @@ import logging
import subprocess
import os
import stat
+import socket
from string import lower
import re
@@ -36,7 +37,6 @@ def realm_to_suffix(realm_name):
terms = ["dc=" + x.lower() for x in s]
return ",".join(terms)
-
def template_str(txt, vars):
return string.Template(txt).substitute(vars)
diff --git a/ipa-server/freeipa-server.spec b/ipa-server/freeipa-server.spec
index 80b77bc9..93a3bae1 100755
--- a/ipa-server/freeipa-server.spec
+++ b/ipa-server/freeipa-server.spec
@@ -71,6 +71,8 @@ rm -rf %{buildroot}
%files
%defattr(-,root,root,-)
%{_sbindir}/ipa-server-install
+%{_sbindir}/ipa-replica-install
+%{_sbindir}/ipa-replica-prepare
%{_sbindir}/ipa_kpasswd
%{_sbindir}/ipa-webgui
%attr(755,root,root) %{_initrddir}/ipa-kpasswd
diff --git a/ipa-server/freeipa-server.spec.in b/ipa-server/freeipa-server.spec.in
index f7db08d7..d50cd4e9 100644
--- a/ipa-server/freeipa-server.spec.in
+++ b/ipa-server/freeipa-server.spec.in
@@ -71,6 +71,8 @@ rm -rf %{buildroot}
%files
%defattr(-,root,root,-)
%{_sbindir}/ipa-server-install
+%{_sbindir}/ipa-replica-install
+%{_sbindir}/ipa-replica-prepare
%{_sbindir}/ipa_kpasswd
%{_sbindir}/ipa-webgui
%attr(755,root,root) %{_initrddir}/ipa-kpasswd
diff --git a/ipa-server/ipa-install/Makefile.am b/ipa-server/ipa-install/Makefile.am
index 9ecf7e20..4765cfb5 100644
--- a/ipa-server/ipa-install/Makefile.am
+++ b/ipa-server/ipa-install/Makefile.am
@@ -6,6 +6,8 @@ SUBDIRS = \
sbin_SCRIPTS = \
ipa-server-install \
+ ipa-replica-install \
+ ipa-replica-prepare \
$(NULL)
appdir = $(IPA_DATA_DIR)
diff --git a/ipa-server/ipa-install/ipa-replica-install b/ipa-server/ipa-install/ipa-replica-install
new file mode 100644
index 00000000..706dc323
--- /dev/null
+++ b/ipa-server/ipa-install/ipa-replica-install
@@ -0,0 +1,142 @@
+#! /usr/bin/python -E
+# Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
+#
+# Copyright (C) 2007 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 or later
+#
+# 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 sys
+sys.path.append("/usr/share/ipa")
+
+import tempfile
+from ConfigParser import SafeConfigParser
+
+from ipa import ipautil
+
+from ipaserver import dsinstance, replication, installutils, krbinstance, service
+from ipaserver import httpinstance, webguiinstance, radiusinstance, ntpinstance
+
+class ReplicaConfig:
+ def __init__(self):
+ self.realm_name = ""
+ self.master_host_name = ""
+ self.dirman_password = ""
+ self.ds_user = ""
+ self.host_name = ""
+ self.repl_password = ""
+ self.dir = ""
+
+def parse_options():
+ from optparse import OptionParser
+ parser = OptionParser()
+ parser.add_option("-r", "--read-only", dest="master", action="store_false",
+ default=True, help="create read-only replica - default is master")
+
+ options, args = parser.parse_args()
+
+ if len(args) != 1:
+ parser.error("you must provide a file generated by ipa-replica-prepare")
+
+ return options, args[0]
+
+def get_dirman_password():
+ return installutils.read_password("Directory Manager (existing master)")
+
+def expand_info(filename):
+ top_dir = tempfile.mkdtemp("ipa")
+ dir = top_dir + "/realm_info"
+ ipautil.run(["tar", "xfz", filename, "-C", top_dir])
+
+ return top_dir, dir
+
+def read_info(dir, rconfig):
+ filename = dir + "/realm_info"
+ fd = open(filename)
+ config = SafeConfigParser()
+ config.readfp(fd)
+
+ rconfig.realm_name = config.get("realm", "realm_name")
+ rconfig.master_host_name = config.get("realm", "master_host_name")
+ rconfig.ds_user = config.get("realm", "ds_user")
+
+def get_host_name():
+ hostname = installutils.get_fqdn()
+ try:
+ installutils.verify_fqdn(hostname)
+ except RuntimeError, e:
+ logging.error(str(e))
+ sys.exit(1)
+
+ return hostname
+
+def install_ds(config):
+ dsinstance.check_existing_installation()
+ dsinstance.check_ports()
+
+ ds = dsinstance.DsInstance()
+ ds.create_instance(config.ds_user, config.realm_name, config.host_name, config.dirman_password)
+
+def install_krb(config):
+ krb = krbinstance.KrbInstance()
+ ldappwd_filename = config.dir + "/ldappwd"
+ krb.create_replica(config.ds_user, config.realm_name, config.host_name,
+ config.dirman_password, ldappwd_filename)
+
+def install_http(config):
+ http = httpinstance.HTTPInstance()
+ http.create_instance(config.realm_name, config.host_name)
+
+def main():
+ options, filename = parse_options()
+ top_dir, dir = expand_info(filename)
+
+ config = ReplicaConfig()
+ read_info(dir, config)
+ config.host_name = get_host_name()
+ config.repl_password = "box"
+ config.dir = dir
+
+ # get the directory manager password
+ config.dirman_password = get_dirman_password()
+
+ install_ds(config)
+
+ repl = replication.ReplicationManager(config.host_name, config.dirman_password)
+ repl.setup_replication(config.master_host_name, config.realm_name, options.master)
+
+ install_krb(config)
+ install_http(config)
+
+ # Create a Web Gui instance
+ webgui = webguiinstance.WebGuiInstance()
+ webgui.create_instance()
+
+ # Create a radius instance
+ radius = radiusinstance.RadiusInstance()
+ # FIXME: ldap_server should be derived, not hardcoded to localhost, also should it be a URL?
+ radius.create_instance(config.realm_name, config.host_name, 'localhost')
+
+ # Configure ntpd
+ ntp = ntpinstance.NTPInstance()
+ ntp.create_instance()
+
+
+ service.restart("dirsrv")
+ service.restart("krb5kdc")
+
+main()
+
+
diff --git a/ipa-server/ipa-install/ipa-replica-prepare b/ipa-server/ipa-install/ipa-replica-prepare
new file mode 100644
index 00000000..705c731d
--- /dev/null
+++ b/ipa-server/ipa-install/ipa-replica-prepare
@@ -0,0 +1,114 @@
+#! /usr/bin/python -E
+# Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
+#
+# Copyright (C) 2007 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 or later
+#
+# 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 sys
+sys.path.append("/usr/share/ipa")
+
+import logging, tempfile, shutil, os, pwd
+from ConfigParser import SafeConfigParser
+import krbV
+
+from ipa import ipautil
+from ipaserver import dsinstance
+from ipaserver import installutils
+
+certutil = "/usr/bin/certutil"
+
+def get_host_name():
+ hostname = installutils.get_fqdn()
+ try:
+ installutils.verify_fqdn(hostname)
+ except RuntimeError, e:
+ logging.error(str(e))
+ sys.exit(1)
+
+ return hostname
+
+def get_realm_name():
+ c = krbV.default_context()
+ return c.default_realm
+
+def check_ipa_configuration(realm_name):
+ config_dir = dsinstance.config_dirname(realm_name)
+ if not ipautil.dir_exists(config_dir):
+ logging.error("could not find directory instance: %s" % config_dir)
+ sys.exit(1)
+
+def create_certdb(ds_dir, dir):
+ # copy the passwd, noise, and pin files
+ shutil.copyfile(ds_dir + "/pwdfile.txt", dir + "/pwdfile.txt")
+ shutil.copyfile(ds_dir + "/noise.txt", dir + "/noise.txt")
+ shutil.copyfile(ds_dir + "/pin.txt", dir + "/pin.txt")
+
+ # create a new cert db
+ ipautil.run([certutil, "-N", "-d", dir, "-f", dir + "/pwdfile.txt"])
+
+ # Add the CA cert
+ ipautil.run([certutil, "-A", "-d", dir, "-n", "CA certificate", "-t", "CT,CT", "-a", "-i",
+ ds_dir + "/cacert.asc"])
+
+def get_ds_user(ds_dir):
+ uid = os.stat(ds_dir).st_uid
+ user = pwd.getpwuid(uid)[0]
+
+ return user
+
+def copy_files(realm_name, dir):
+ shutil.copy("/var/kerberos/krb5kdc/ldappwd", dir + "/ldappwd")
+
+
+def save_config(dir, realm_name, host_name, ds_user):
+ config = SafeConfigParser()
+ config.add_section("realm")
+ config.set("realm", "realm_name", realm_name)
+ config.set("realm", "master_host_name", host_name)
+ config.set("realm", "ds_user", ds_user)
+ fd = open(dir + "/realm_info", "w")
+ config.write(fd)
+
+
+def main():
+ realm_name = get_realm_name()
+ host_name = get_host_name()
+ ds_dir = dsinstance.config_dirname(realm_name)
+ ds_user = get_ds_user(ds_dir)
+
+ check_ipa_configuration(realm_name)
+
+ top_dir = tempfile.mkdtemp("ipa")
+ dir = top_dir + "/realm_info"
+ os.mkdir(dir, 0700)
+
+ create_certdb(ds_dir, dir)
+
+ copy_files(realm_name, dir)
+
+ save_config(dir, realm_name, host_name, ds_user)
+
+ ipautil.run(["/bin/tar", "cfz", "replica-info-" + realm_name, "-C", top_dir, "realm_info"])
+
+ shutil.rmtree(dir)
+
+main()
+
+
+
+
+
diff --git a/ipa-server/ipa-install/ipa-server-install b/ipa-server/ipa-install/ipa-server-install
index 2de687fd..b957e522 100644
--- a/ipa-server/ipa-install/ipa-server-install
+++ b/ipa-server/ipa-install/ipa-server-install
@@ -34,7 +34,6 @@ import socket
import errno
import logging
import pwd
-import getpass
import subprocess
import signal
import shutil
@@ -51,8 +50,9 @@ import ipaserver.radiusinstance
import ipaserver.webguiinstance
from ipaserver import service
+from ipaserver.installutils import *
-from ipa.ipautil import run
+from ipa.ipautil import *
def parse_options():
parser = OptionParser(version=VERSION)
@@ -86,39 +86,6 @@ def parse_options():
return options
-def logging_setup(options):
- # Always log everything (i.e., DEBUG) to the log
- # file.
- logging.basicConfig(level=logging.DEBUG,
- format='%(asctime)s %(levelname)s %(message)s',
- filename='ipaserver-install.log',
- filemode='w')
-
- console = logging.StreamHandler()
- # If the debug option is set, also log debug messages to the console
- if options.debug:
- console.setLevel(logging.DEBUG)
- else:
- # Otherwise, log critical and error messages
- console.setLevel(logging.ERROR)
- formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
- console.setFormatter(formatter)
- logging.getLogger('').addHandler(console)
-
-def erase_ds_instance_data(serverid):
- try:
- shutil.rmtree("/etc/dirsrv/slapd-%s" % serverid)
- except:
- pass
- try:
- shutil.rmtree("/var/lib/dirsrv/slapd-%s" % serverid)
- except:
- pass
- try:
- shutil.rmtree("/var/lock/dirsrv/slapd-%s" % serverid)
- except:
- pass
-
def signal_handler(signum, frame):
global ds
print "\nCleaning up..."
@@ -126,59 +93,9 @@ def signal_handler(signum, frame):
print "Removing configuration for %s instance" % ds.serverid
ds.stop()
if ds.serverid:
- erase_ds_instance_data (ds.serverid)
+ ipaserver.dsinstance.erase_ds_instance_data (ds.serverid)
sys.exit(1)
-def check_existing_installation():
- dirs = glob.glob("/etc/dirsrv/slapd-*")
- if not dirs:
- return
- print ""
- print "An existing Directory Server has been detected."
- yesno = raw_input("Do you wish to remove it and create a new one? [no]: ")
- if not yesno or yesno.lower()[0] != "y":
- sys.exit(1)
-
- try:
- run(["/sbin/service", "dirsrv", "stop"])
- except:
- pass
- for d in dirs:
- serverid = os.path.basename(d).split("slapd-", 1)[1]
- if serverid:
- erase_ds_instance_data(serverid)
-
-def check_ports():
- ds_unsecure = port_available(389)
- ds_secure = port_available(636)
- if not ds_unsecure or not ds_secure:
- print "IPA requires ports 389 and 636 for the Directory Server."
- print "These are currently in use:"
- if not ds_unsecure:
- print "\t389"
- if not ds_secure:
- print "\t636"
- sys.exit(1)
-
-def get_fqdn():
- fqdn = ""
- try:
- fqdn = socket.getfqdn()
- except:
- try:
- fqdn = socket.gethostname()
- except:
- fqdn = ""
- return fqdn
-
-def verify_fqdn(host_name):
- is_ok = True
- if len(host_name.split(".")) < 2 or host_name == "localhost.localdomain":
- print "Invalid hostname: " + host_name
- print "This host name can't be used as a hostname for an IPA Server"
- is_ok = False
- return is_ok
-
def read_host_name(host_default):
host_ok = False
host_name = ""
@@ -198,7 +115,9 @@ def read_host_name(host_default):
host_name = host_default
else:
host_name = host_input
- if not verify_fqdn(host_name):
+ try:
+ verify_fqdn(host_name)
+ except:
host_name = ""
continue
else:
@@ -256,36 +175,6 @@ def read_ip_address(host_name):
return ip
-def port_available(port):
- """Try to bind to a port on the wildcard host
- Return 1 if the port is available
- Return 0 if the port is in use
- """
- rv = 1
-
- try:
- s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- s.bind(('', port))
- s.shutdown(0)
- s.close()
- except socket.error, e:
- if e[0] == errno.EADDRINUSE:
- rv = 0
-
- if rv:
- try:
- s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
- s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
- s.bind(('', port))
- s.shutdown(0)
- s.close()
- except socket.error, e:
- if e[0] == errno.EADDRINUSE:
- rv = 0
-
- return rv
-
def read_ds_user():
print "The server must run as a specific user in a specific group."
print "It is strongly recommended that this user should have no privileges"
@@ -333,23 +222,6 @@ def read_realm_name(domain_name):
realm_name = upper_dom
return realm_name
-def read_password(user):
- correct = False
- pwd = ""
- while not correct:
- pwd = getpass.getpass(user + " password: ")
- if not pwd:
- continue
- pwd_confirm = getpass.getpass("Password (confirm): ")
- if pwd != pwd_confirm:
- print "Password mismatch!"
- print ""
- else:
- correct = True
- #TODO: check validity/length
- print ""
- return pwd
-
def read_dm_password():
print "Certain directory server operations require an administrative user."
print "This user is referred to as the Directory Manager and has full access"
@@ -392,6 +264,8 @@ def main():
global ds
ds = None
+ options = parse_options()
+
if os.getegid() != 0:
print "Must be root to setup server"
return
@@ -399,17 +273,17 @@ def main():
signal.signal(signal.SIGTERM, signal_handler)
signal.signal(signal.SIGINT, signal_handler)
+ standard_logging_setup("ipaserver-install.log", options.debug)
+
print "=============================================================================="
print "This program will setup the FreeIPA Server."
print ""
print "To accept the default shown in brackets, press the Enter key."
print ""
- check_existing_installation()
- check_ports()
+ ipaserver.dsinstance.check_existing_installation()
+ ipaserver.dsinstance.check_ports()
- options = parse_options()
- logging_setup(options)
ds_user = ""
realm_name = ""
@@ -439,10 +313,13 @@ def main():
host_default = get_fqdn()
if options.unattended:
- if not verify_fqdn(host_default):
+ try:
+ verify_fqdn(host_default)
+ except RuntimeError, e:
+ logging.error(str(e) + "\n")
return "-Fatal Error-"
- else:
- host_name = host_default
+
+ host_name = host_default
else:
host_name = read_host_name(host_default)
diff --git a/ipa-server/ipa-install/share/kerberos.ldif b/ipa-server/ipa-install/share/kerberos.ldif
index d55f39ce..75057aa3 100644
--- a/ipa-server/ipa-install/share/kerberos.ldif
+++ b/ipa-server/ipa-install/share/kerberos.ldif
@@ -14,22 +14,4 @@ objectClass: top
cn: kerberos
aci: (targetattr="*")(version 3.0; acl "KDC System Account"; allow (all) userdn= "ldap:///uid=kdc,cn=sysaccounts,cn=etc,$SUFFIX";)
-#sasl mapping
-dn: cn=Full Principal,cn=mapping,cn=sasl,cn=config
-changetype: add
-objectclass: top
-objectclass: nsSaslMapping
-cn: Full Principal
-nsSaslMapRegexString: \(.*\)@\(.*\)
-nsSaslMapBaseDNTemplate: $SUFFIX
-nsSaslMapFilterTemplate: (krbPrincipalName=\1@\2)
-
-dn: cn=Name Only,cn=mapping,cn=sasl,cn=config
-changetype: add
-objectclass: top
-objectclass: nsSaslMapping
-cn: Name Only
-nsSaslMapRegexString: \(.*\)
-nsSaslMapBaseDNTemplate: $SUFFIX
-nsSaslMapFilterTemplate: (krbPrincipalName=\1@$REALM)
diff --git a/ipa-server/ipaserver/Makefile.am b/ipa-server/ipaserver/Makefile.am
index 25b85687..c2d164b9 100644
--- a/ipa-server/ipaserver/Makefile.am
+++ b/ipa-server/ipaserver/Makefile.am
@@ -12,6 +12,8 @@ app_PYTHON = \
radiusinstance.py \
webguiinstance.py \
service.py \
+ installutils.py \
+ replication.py \
$(NULL)
EXTRA_DIST = \
diff --git a/ipa-server/ipaserver/dsinstance.py b/ipa-server/ipaserver/dsinstance.py
index 3cf80f46..79a57182 100644
--- a/ipa-server/ipaserver/dsinstance.py
+++ b/ipa-server/ipaserver/dsinstance.py
@@ -24,10 +24,14 @@ import tempfile
import shutil
import logging
import pwd
+import glob
+import sys
from ipa.ipautil import *
import service
+import installutils
+
SERVER_ROOT_64 = "/usr/lib64/dirsrv"
SERVER_ROOT_32 = "/usr/lib/dirsrv"
@@ -35,9 +39,6 @@ def ldap_mod(fd, dn, pwd):
args = ["/usr/bin/ldapmodify", "-h", "127.0.0.1", "-xv", "-D", dn, "-w", pwd, "-f", fd.name]
run(args)
- text = fd.read()
- print text
-
def realm_to_suffix(realm_name):
s = realm_name.split(".")
terms = ["dc=" + x.lower() for x in s]
@@ -49,6 +50,61 @@ def find_server_root():
else:
return SERVER_ROOT_32
+def realm_to_serverid(realm_name):
+ return "-".join(realm_name.split("."))
+
+def config_dirname(realm_name):
+ return "/etc/dirsrv/slapd-" + realm_to_serverid(realm_name) + "/"
+
+def schema_dirname(realm_name):
+ return config_dirname(realm_name) + "/schema/"
+
+def erase_ds_instance_data(serverid):
+ try:
+ shutil.rmtree("/etc/dirsrv/slapd-%s" % serverid)
+ except:
+ pass
+ try:
+ shutil.rmtree("/var/lib/dirsrv/slapd-%s" % serverid)
+ except:
+ pass
+ try:
+ shutil.rmtree("/var/lock/dirsrv/slapd-%s" % serverid)
+ except:
+ pass
+
+def check_existing_installation():
+ dirs = glob.glob("/etc/dirsrv/slapd-*")
+ if not dirs:
+ return
+ print ""
+ print "An existing Directory Server has been detected."
+ yesno = raw_input("Do you wish to remove it and create a new one? [no]: ")
+ if not yesno or yesno.lower()[0] != "y":
+ sys.exit(1)
+
+ try:
+ run(["/sbin/service", "dirsrv", "stop"])
+ except:
+ pass
+ for d in dirs:
+ serverid = os.path.basename(d).split("slapd-", 1)[1]
+ if serverid:
+ erase_ds_instance_data(serverid)
+
+def check_ports():
+ ds_unsecure = installutils.port_available(389)
+ ds_secure = installutils.port_available(636)
+ if not ds_unsecure or not ds_secure:
+ print "IPA requires ports 389 and 636 for the Directory Server."
+ print "These are currently in use:"
+ if not ds_unsecure:
+ print "\t389"
+ if not ds_secure:
+ print "\t636"
+ sys.exit(1)
+
+
INF_TEMPLATE = """
[General]
FullMachineName= $FQHN
@@ -72,20 +128,25 @@ class DsInstance(service.Service):
self.dm_password = None
self.sub_dict = None
- def create_instance(self, ds_user, realm_name, host_name, dm_password):
+ def create_instance(self, ds_user, realm_name, host_name, dm_password, ro_replica=False):
self.ds_user = ds_user
self.realm_name = realm_name.upper()
- self.serverid = "-".join(self.realm_name.split("."))
+ self.serverid = realm_to_serverid(self.realm_name)
self.suffix = realm_to_suffix(self.realm_name)
self.host_name = host_name
self.dm_password = dm_password
self.__setup_sub_dict()
+
+ if ro_replica:
+ self.start_creation(15, "Configuring directory server:")
+ else:
+ self.start_creation(15, "Configuring directory server:")
- self.start_creation(15, "Configuring directory server:")
self.__create_ds_user()
self.__create_instance()
self.__add_default_schemas()
- self.__add_memberof_module()
+ if not ro_replica:
+ self.__add_memberof_module()
self.__add_referint_module()
self.__add_dna_module()
self.__create_indeces()
@@ -97,10 +158,11 @@ class DsInstance(service.Service):
except:
# TODO: roll back here?
logging.critical("Failed to restart the ds instance")
- self.__config_uidgid_gen_first_master()
self.__add_default_layout()
- self.__add_master_entry_first_master()
- self.__init_memberof()
+ if not ro_replica:
+ self.__config_uidgid_gen_first_master()
+ self.__add_master_entry_first_master()
+ self.__init_memberof()
self.step("configuring directoy to start on boot")
@@ -108,14 +170,6 @@ class DsInstance(service.Service):
self.done_creation()
- def config_dirname(self):
- if not self.serverid:
- raise RuntimeError("serverid not set")
- return "/etc/dirsrv/slapd-" + self.serverid + "/"
-
- def schema_dirname(self):
- return self.config_dirname() + "/schema/"
-
def __setup_sub_dict(self):
server_root = find_server_root()
self.sub_dict = dict(FQHN=self.host_name, SERVERID=self.serverid,
@@ -165,13 +219,13 @@ class DsInstance(service.Service):
def __add_default_schemas(self):
self.step("adding default schema")
shutil.copyfile(SHARE_DIR + "60kerberos.ldif",
- self.schema_dirname() + "60kerberos.ldif")
+ schema_dirname(self.realm_name) + "60kerberos.ldif")
shutil.copyfile(SHARE_DIR + "60samba.ldif",
- self.schema_dirname() + "60samba.ldif")
+ schema_dirname(self.realm_name) + "60samba.ldif")
shutil.copyfile(SHARE_DIR + "60radius.ldif",
- self.schema_dirname() + "60radius.ldif")
+ schema_dirname(self.realm_name) + "60radius.ldif")
shutil.copyfile(SHARE_DIR + "60ipaconfig.ldif",
- self.schema_dirname() + "60ipaconfig.ldif")
+ schema_dirname(self.realm_name) + "60ipaconfig.ldif")
def __add_memberof_module(self):
self.step("enabling memboerof plugin")
@@ -235,7 +289,7 @@ class DsInstance(service.Service):
def __enable_ssl(self):
self.step("configuring ssl for ds instance")
- dirname = self.config_dirname()
+ dirname = config_dirname(self.realm_name)
args = ["/usr/share/ipa/ipa-server-setupssl", self.dm_password,
dirname, self.host_name]
try:
@@ -273,7 +327,7 @@ class DsInstance(service.Service):
def __certmap_conf(self):
self.step("configuring certmap.conf")
- dirname = self.config_dirname()
+ dirname = config_dirname(self.realm_name)
certmap_conf = template_file(SHARE_DIR+"certmap.conf.template", self.sub_dict)
certmap_fd = open(dirname+"certmap.conf", "w+")
certmap_fd.write(certmap_conf)
@@ -281,7 +335,7 @@ class DsInstance(service.Service):
def change_admin_password(self, password):
logging.debug("Changing admin password")
- dirname = self.config_dirname()
+ dirname = config_dirname(self.realm_name)
if dir_exists("/usr/lib64/mozldap"):
app = "/usr/lib64/mozldap/ldappasswd"
else:
diff --git a/ipa-server/ipaserver/installutils.py b/ipa-server/ipaserver/installutils.py
new file mode 100644
index 00000000..a403e815
--- /dev/null
+++ b/ipa-server/ipaserver/installutils.py
@@ -0,0 +1,108 @@
+# Authors: Simo Sorce <ssorce@redhat.com>
+#
+# Copyright (C) 2007 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 or later
+#
+# 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 socket
+import errno
+import getpass
+
+def get_fqdn():
+ fqdn = ""
+ try:
+ fqdn = socket.getfqdn()
+ except:
+ try:
+ fqdn = socket.gethostname()
+ except:
+ fqdn = ""
+ return fqdn
+
+def verify_fqdn(host_name):
+ if len(host_name.split(".")) < 2 or host_name == "localhost.localdomain":
+ raise RuntimeError("Invalid hostname: " + host_name)
+
+def port_available(port):
+ """Try to bind to a port on the wildcard host
+ Return 1 if the port is available
+ Return 0 if the port is in use
+ """
+ rv = 1
+
+ try:
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ s.bind(('', port))
+ s.shutdown(0)
+ s.close()
+ except socket.error, e:
+ if e[0] == errno.EADDRINUSE:
+ rv = 0
+
+ if rv:
+ try:
+ s = socket.socket(socket.AF_INET6, socket.SOCK_STREAM)
+ s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ s.bind(('', port))
+ s.shutdown(0)
+ s.close()
+ except socket.error, e:
+ if e[0] == errno.EADDRINUSE:
+ rv = 0
+
+ return rv
+
+def standard_logging_setup(log_filename, debug=False):
+ # Always log everything (i.e., DEBUG) to the log
+ # file.
+ logging.basicConfig(level=logging.DEBUG,
+ format='%(asctime)s %(levelname)s %(message)s',
+ filename=log_filename,
+ filemode='w')
+
+ console = logging.StreamHandler()
+ # If the debug option is set, also log debug messages to the console
+ if debug:
+ console.setLevel(logging.DEBUG)
+ else:
+ # Otherwise, log critical and error messages
+ console.setLevel(logging.ERROR)
+ formatter = logging.Formatter('%(name)-12s: %(levelname)-8s %(message)s')
+ console.setFormatter(formatter)
+ logging.getLogger('').addHandler(console)
+
+def read_password(user):
+ correct = False
+ pwd = ""
+ while not correct:
+ pwd = getpass.getpass(user + " password: ")
+ if not pwd:
+ continue
+ if len(pwd) < 8:
+ print "Password must be at least 8 characters long"
+ continue
+ pwd_confirm = getpass.getpass("Password (confirm): ")
+ if pwd != pwd_confirm:
+ print "Password mismatch!"
+ print ""
+ else:
+ correct = True
+ print ""
+ return pwd
+
+
diff --git a/ipa-server/ipaserver/ipaldap.py b/ipa-server/ipaserver/ipaldap.py
index d319869d..ef8becec 100644
--- a/ipa-server/ipaserver/ipaldap.py
+++ b/ipa-server/ipaserver/ipaldap.py
@@ -176,25 +176,90 @@ def wrapper(f,name):
return f(*args, **kargs)
return inner
+class LDIFConn(ldif.LDIFParser):
+ def __init__(
+ self,
+ input_file,
+ ignored_attr_types=None,max_entries=0,process_url_schemes=None
+ ):
+ """
+ See LDIFParser.__init__()
+
+ Additional Parameters:
+ all_records
+ List instance for storing parsed records
+ """
+ self.dndict = {} # maps dn to Entry
+ self.dnlist = [] # contains entries in order read
+ myfile = input_file
+ if isinstance(input_file,str) or isinstance(input_file,unicode):
+ myfile = open(input_file, "r")
+ ldif.LDIFParser.__init__(self,myfile,ignored_attr_types,max_entries,process_url_schemes)
+ self.parse()
+ if isinstance(input_file,str) or isinstance(input_file,unicode):
+ myfile.close()
+
+ def handle(self,dn,entry):
+ """
+ Append single record to dictionary of all records.
+ """
+ if not dn:
+ dn = ''
+ newentry = Entry((dn, entry))
+ self.dndict[IPAdmin.normalizeDN(dn)] = newentry
+ self.dnlist.append(newentry)
+
+ def get(self,dn):
+ ndn = IPAdmin.normalizeDN(dn)
+ return self.dndict.get(ndn, Entry(None))
+
class IPAdmin(SimpleLDAPObject):
CFGSUFFIX = "o=NetscapeRoot"
DEFAULT_USER_ID = "nobody"
+
+ def getDseAttr(self,attrname):
+ conffile = self.confdir + '/dse.ldif'
+ dseldif = LDIFConn(conffile)
+ cnconfig = dseldif.get("cn=config")
+ if cnconfig:
+ return cnconfig.getValue(attrname)
+ return None
def __initPart2(self):
if self.binddn and len(self.binddn) and not hasattr(self,'sroot'):
try:
ent = self.getEntry('cn=config', ldap.SCOPE_BASE, '(objectclass=*)',
- [ 'nsslapd-instancedir', 'nsslapd-errorlog' ])
- instdir = ent.getValue('nsslapd-instancedir')
- self.sroot, self.inst = re.match(r'(.*)[\/]slapd-(\w+)$', instdir).groups()
+ [ 'nsslapd-instancedir', 'nsslapd-errorlog',
+ 'nsslapd-certdir', 'nsslapd-schemadir' ])
self.errlog = ent.getValue('nsslapd-errorlog')
- except (ldap.INSUFFICIENT_ACCESS, ldap.CONNECT_ERROR,
- ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND)):
+ self.confdir = None
+ if self.isLocal:
+ self.confdir = ent.getValue('nsslapd-certdir')
+ if not self.confdir or not os.access(self.confdir + '/dse.ldif', os.R_OK):
+ self.confdir = ent.getValue('nsslapd-schemadir')
+ if self.confdir:
+ self.confdir = os.path.dirname(self.confdir)
+ instdir = ent.getValue('nsslapd-instancedir')
+ if not instdir:
+ # get instance name from errorlog
+ self.inst = re.match(r'(.*)[\/]slapd-([\w-]+)/errors', self.errlog).group(2)
+ if self.confdir:
+ instdir = self.getDseAttr('nsslapd-instancedir')
+ else:
+ if self.isLocal:
+ print instdir
+ self.sroot, self.inst = re.match(r'(.*)[\/]slapd-([\w-]+)$', instdir).groups()
+ instdir = re.match(r'(.*/slapd-.*)/errors', self.errlog).group(1)
+ #self.sroot, self.inst = re.match(r'(.*)[\/]slapd-([\w-]+)$', instdir).groups()
+ ent = self.getEntry('cn=config,cn=ldbm database,cn=plugins,cn=config',
+ ldap.SCOPE_BASE, '(objectclass=*)',
+ [ 'nsslapd-directory' ])
+ self.dbdir = os.path.dirname(ent.getValue('nsslapd-directory'))
+ except (ldap.INSUFFICIENT_ACCESS, ldap.CONNECT_ERROR):
pass # usually means
-# print "ignored exception"
except ldap.LDAPError, e:
print "caught exception ", e
- raise ipaerror.gen_exception(ipaerror.LDAP_DATABASE_ERROR, None, e)
+ raise
def __localinit__(self):
"""If a CA certificate is provided then it is assumed that we are
@@ -209,7 +274,7 @@ class IPAdmin(SimpleLDAPObject):
else:
SimpleLDAPObject.__init__(self,'ldap://%s:%d' % (self.host,self.port))
- def __init__(self,host,port,cacert,bindcert,bindkey,proxydn=None,debug=None):
+ def __init__(self,host,port=389,cacert=None,bindcert=None,bindkey=None,proxydn=None,debug=None):
"""We just set our instance variables and wrap the methods - the real
work is done in __localinit__ and __initPart2 - these are separated
out this way so that we can call them from places other than
@@ -223,7 +288,7 @@ class IPAdmin(SimpleLDAPObject):
ldap.set_option(ldap.OPT_X_TLS_KEYFILE,bindkey)
self.__wrapmethods()
- self.port = port or 389
+ self.port = port
self.host = host
self.cacert = cacert
self.bindcert = bindcert
@@ -272,6 +337,12 @@ class IPAdmin(SimpleLDAPObject):
self.principal = principal
self.proxydn = None
+ def do_simple_bind(self, binddn="cn=directory manager", bindpw=""):
+ self.binddn = binddn
+ self.bindpwd = bindpw
+ self.simple_bind_s(binddn, bindpw)
+ self.__initPart2()
+
def getEntry(self,*args):
"""This wraps the search function. It is common to just get one entry"""
@@ -283,8 +354,9 @@ class IPAdmin(SimpleLDAPObject):
try:
res = self.search(*args)
type, obj = self.result(res)
-
- # res = self.search_ext(args[0], args[1], filterstr=args[2], attrlist=args[3], serverctrls=sctrl)
+ except ldap.NO_SUCH_OBJECT:
+ raise ipaerror.gen_exception(ipaerror.LDAP_NOT_FOUND,
+ "no such entry for " + str(args))
except ldap.LDAPError, e:
raise ipaerror.gen_exception(ipaerror.LDAP_DATABASE_ERROR, None, e)
@@ -538,7 +610,7 @@ class IPAdmin(SimpleLDAPObject):
print "Export task %s for file %s completed successfully" % (cn,file)
return rc
- def waitForEntry(self, dn, timeout=7200, attr='', quiet=False):
+ def waitForEntry(self, dn, timeout=7200, attr='', quiet=True):
scope = ldap.SCOPE_BASE
filter = "(objectclass=*)"
attrlist = []
@@ -560,7 +632,8 @@ class IPAdmin(SimpleLDAPObject):
entry = self.getEntry(dn, scope, filter, attrlist)
except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND):
pass # found entry, but no attr
- except ldap.NO_SUCH_OBJECT: pass # no entry yet
+ except ldap.NO_SUCH_OBJECT:
+ pass # no entry yet
except ldap.LDAPError, e: # badness
print "\nError reading entry", dn, e
break
@@ -574,7 +647,7 @@ class IPAdmin(SimpleLDAPObject):
print "\nwaitForEntry timeout for %s for %s" % (self,dn)
elif entry and not quiet:
print "\nThe waited for entry is:", entry
- else:
+ elif not entry:
print "\nError: could not read entry %s from %s" % (dn,self)
return entry
diff --git a/ipa-server/ipaserver/krbinstance.py b/ipa-server/ipaserver/krbinstance.py
index 827c9815..aca9e261 100644
--- a/ipa-server/ipaserver/krbinstance.py
+++ b/ipa-server/ipaserver/krbinstance.py
@@ -32,16 +32,21 @@ import os
import pwd
import socket
import time
+import shutil
import service
from ipa.ipautil import *
+from ipa import ipaerror
+
+import ipaldap
import ldap
from ldap import LDAPError
from ldap import ldapobject
-from pyasn1.type import univ
+from pyasn1.type import univ, namedtype
import pyasn1.codec.ber.encoder
+import pyasn1.codec.ber.decoder
import struct
import base64
@@ -88,18 +93,26 @@ class KrbInstance(service.Service):
self.kdc_password = None
self.sub_dict = None
- def create_instance(self, ds_user, realm_name, host_name, admin_password, master_password):
+ def __common_setup(self, ds_user, realm_name, host_name, admin_password):
self.ds_user = ds_user
- self.fqdn = host_name
- self.ip = socket.gethostbyname(host_name)
+ self.fqdn = host_name
self.realm = realm_name.upper()
self.host = host_name.split(".")[0]
- self.domain = host_to_domain(host_name)
- self.admin_password = admin_password
- self.master_password = master_password
-
+ self.ip = socket.gethostbyname(host_name)
+ self.domain = host_to_domain(host_name)
self.suffix = realm_to_suffix(self.realm)
self.kdc_password = generate_kdc_password()
+ self.admin_password = admin_password
+
+ self.__setup_sub_dict()
+
+ # get a connection to the DS
+ try:
+ self.conn = ipaldap.IPAdmin(self.fqdn)
+ self.conn.do_simple_bind(bindpw=self.admin_password)
+ except ipaerror.exception_for(ipaerror.LDAP_DATABASE_ERROR), e:
+ logging.critical("Could not connect to DS")
+ raise e
try:
self.stop()
@@ -107,22 +120,7 @@ class KrbInstance(service.Service):
# It could have been not running
pass
- self.start_creation(10, "Configuring Kerberos KDC")
-
- self.__configure_kdc_account_password()
-
- self.__setup_sub_dict()
-
- self.__configure_ldap()
-
- self.__create_instance()
-
- self.__create_ds_keytab()
-
- self.__export_kadmin_changepw_keytab()
-
- self.__add_pwd_extop_module()
-
+ def __common_post_setup(self):
try:
self.step("starting the KDC")
self.start()
@@ -138,8 +136,48 @@ class KrbInstance(service.Service):
self.step("starting ipa-kpasswd")
service.start("ipa-kpasswd")
+
+ def create_instance(self, ds_user, realm_name, host_name, admin_password, master_password):
+ self.master_password = master_password
+
+ self.__common_setup(ds_user, realm_name, host_name, admin_password)
+
+ self.start_creation(11, "Configuring Kerberos KDC")
+
+ self.__configure_kdc_account_password()
+ self.__configure_sasl_mappings()
+ self.__add_krb_entries()
+ self.__create_instance()
+ self.__create_ds_keytab()
+ self.__export_kadmin_changepw_keytab()
+ self.__add_pwd_extop_module()
+
+ self.__common_post_setup()
+
+ self.done_creation()
+
+
+ def create_replica(self, ds_user, realm_name, host_name, admin_password, ldap_passwd_filename):
+
+ self.__common_setup(ds_user, realm_name, host_name, admin_password)
+
+ self.start_creation(9, "Configuring Kerberos KDC")
+ self.__copy_ldap_passwd(ldap_passwd_filename)
+ self.__configure_sasl_mappings()
+ self.__write_stash_from_ds()
+ self.__create_instance(replica=True)
+ self.__create_ds_keytab()
+ self.__export_kadmin_changepw_keytab()
+
+ self.__common_post_setup()
+
self.done_creation()
+
+ def __copy_ldap_passwd(self, filename):
+ shutil.copy(filename, "/var/kerberos/krb5kdc/ldappwd")
+
+
def __configure_kdc_account_password(self):
self.step("setting KDC account password")
hexpwd = ''
@@ -158,23 +196,60 @@ class KrbInstance(service.Service):
HOST=self.host,
REALM=self.realm)
- def __configure_ldap(self):
- self.step("adding kerberos configuration to the directory")
+ def __configure_sasl_mappings(self):
+ self.step("adding sasl mappings to the directory")
# we need to remove any existing SASL mappings in the directory as otherwise they
# they may conflict. There is no way to define the order they are used in atm.
+
+ # FIXME: for some reason IPAdmin dies here, so we switch
+ # it out for a regular ldapobject.
+ conn = self.conn
+ self.conn = ldapobject.SimpleLDAPObject("ldap://127.0.0.1/")
+ self.conn.bind("cn=directory manager", self.admin_password)
try:
- lo = ldapobject.SimpleLDAPObject("ldap://127.0.0.1/")
- lo.bind("cn=Directory Manager", self.admin_password)
- msgid = lo.search("cn=mapping,cn=sasl,cn=config", ldap.SCOPE_ONELEVEL, "(objectclass=nsSaslMapping)")
- res = lo.result(msgid)
+ msgid = self.conn.search("cn=mapping,cn=sasl,cn=config", ldap.SCOPE_ONELEVEL, "(objectclass=nsSaslMapping)")
+ res = self.conn.result(msgid)
for r in res[1]:
- mid = lo.delete(r[0])
- delres = lo.result(mid)
- lo.unbind()
- except LDAPError, e:
- logging.critical("Error during SASL mapping removal: %s" % str(e))
+ mid = self.conn.delete_s(r[0])
+ #except LDAPError, e:
+ # logging.critical("Error during SASL mapping removal: %s" % str(e))
+ except Exception, e:
+ print type(e)
+ print dir(e)
+ raise e
+
+ self.conn = conn
+
+ entry = ipaldap.Entry("cn=Full Principal,cn=mapping,cn=sasl,cn=config")
+ entry.setValues("objectclass", "top", "nsSaslMapping")
+ entry.setValues("cn", "Full Principal")
+ entry.setValues("nsSaslMapRegexString", '\(.*\)@\(.*\)')
+ entry.setValues("nsSaslMapBaseDNTemplate", self.suffix)
+ entry.setValues("nsSaslMapFilterTemplate", '(krbPrincipalName=\\1@\\2)')
+
+ try:
+ self.conn.add_s(entry)
+ except ldap.ALREADY_EXISTS:
+ logging.critical("failed to add Full Principal Sasl mapping")
+ raise e
+
+ entry = ipaldap.Entry("cn=Name Only,cn=mapping,cn=sasl,cn=config")
+ entry.setValues("objectclass", "top", "nsSaslMapping")
+ entry.setValues("cn", "Name Only")
+ entry.setValues("nsSaslMapRegexString", '\(.*\)')
+ entry.setValues("nsSaslMapBaseDNTemplate", self.suffix)
+ entry.setValues("nsSaslMapFilterTemplate", '(krbPrincipalName=\\1@%s)' % self.realm)
+
+ try:
+ self.conn.add_s(entry)
+ except ldap.ALREADY_EXISTS:
+ logging.critical("failed to add Name Only Sasl mapping")
+ raise e
+
+ def __add_krb_entries(self):
+ self.step("adding kerberos entries to the DS")
- #TODO: test that the ldif is ok with any random charcter we may use in the password
+ #TODO: test that the ldif is ok with any random charcter we may use in the password
kerberos_txt = template_file(SHARE_DIR + "kerberos.ldif", self.sub_dict)
kerberos_fd = write_tmp_file(kerberos_txt)
try:
@@ -192,7 +267,7 @@ class KrbInstance(service.Service):
logging.critical("Failed to load default-aci.ldif: %s" % str(e))
aci_fd.close()
- def __create_instance(self):
+ def __create_instance(self, replica=False):
self.step("configuring KDC")
kdc_conf = template_file(SHARE_DIR+"kdc.conf.template", self.sub_dict)
kdc_fd = open("/var/kerberos/krb5kdc/kdc.conf", "w+")
@@ -220,12 +295,34 @@ class KrbInstance(service.Service):
krb_fd.write(krb_realm)
krb_fd.close()
- #populate the directory with the realm structure
- args = ["/usr/kerberos/sbin/kdb5_ldap_util", "-D", "uid=kdc,cn=sysaccounts,cn=etc,"+self.suffix, "-w", self.kdc_password, "create", "-s", "-P", self.master_password, "-r", self.realm, "-subtrees", self.suffix, "-sscope", "sub"]
+ if not replica:
+ #populate the directory with the realm structure
+ args = ["/usr/kerberos/sbin/kdb5_ldap_util", "-D", "uid=kdc,cn=sysaccounts,cn=etc,"+self.suffix, "-w", self.kdc_password, "create", "-s", "-P", self.master_password, "-r", self.realm, "-subtrees", self.suffix, "-sscope", "sub"]
+ try:
+ run(args)
+ except subprocess.CalledProcessError, e:
+ print "Failed to populate the realm structure in kerberos", e
+
+ def __write_stash_from_ds(self):
+ self.step("writing stash file from DS")
try:
- run(args)
- except subprocess.CalledProcessError, e:
- print "Failed to populate the realm structure in kerberos", e
+ entry = self.conn.getEntry("cn=%s, cn=kerberos, %s" % (self.realm, self.suffix), ldap.SCOPE_SUBTREE)
+ except ipaerror.exception_for(ipaerror.LDAP_NOT_FOUND), e:
+ logging.critical("Could not find master key in DS")
+ raise e
+
+ krbMKey = pyasn1.codec.ber.decoder.decode(entry.krbmkey)
+ keytype = int(krbMKey[0][1][0])
+ keydata = str(krbMKey[0][1][1])
+
+ format = '=hi%ss' % len(keydata)
+ s = struct.pack(format, keytype, len(keydata), keydata)
+ try:
+ fd = open("/var/kerberos/krb5kdc/.k5."+self.realm, "w")
+ fd.write(s)
+ except os.error, e:
+ logging.critical("failed to write stash file")
+ raise e
#add the password extop module
def __add_pwd_extop_module(self):
@@ -255,18 +352,14 @@ class KrbInstance(service.Service):
krbMKey.setComponentByPosition(1, MasterKey)
asn1key = pyasn1.codec.ber.encoder.encode(krbMKey)
- #put the attribute in the Directory
- mod_txt = "dn: cn="+self.realm+",cn=kerberos,"+self.suffix+"\n"
- mod_txt += "changetype: modify\n"
- mod_txt += "add: krbMKey\n"
- mod_txt += "krbMKey:: "+base64.encodestring(asn1key)+"\n"
- mod_txt += "\n"
- mod_fd = write_tmp_file(mod_txt)
+ entry = ipaldap.Entry("cn="+self.realm+",cn=kerberos,"+self.suffix)
+ dn = "cn="+self.realm+",cn=kerberos,"+self.suffix
+ mod = [(ldap.MOD_ADD, 'krbMKey', str(asn1key))]
try:
- ldap_mod(mod_fd, "cn=Directory Manager", self.admin_password)
- except subprocess.CalledProcessError, e:
- logging.critical("Failed to load Master Key: %s" % str(e))
- mod_fd.close()
+ self.conn.modify_s(dn, mod)
+ except ldap.TYPE_OR_VALUE_EXISTS, e:
+ logging.critical("failed to add master key to kerberos database\n")
+ raise e
def __create_ds_keytab(self):
self.step("creating a keytab for the directory")
diff --git a/ipa-server/ipaserver/radiusinstance.py b/ipa-server/ipaserver/radiusinstance.py
index 2aee09b3..72cfe6cb 100644
--- a/ipa-server/ipaserver/radiusinstance.py
+++ b/ipa-server/ipaserver/radiusinstance.py
@@ -25,6 +25,7 @@ import shutil
import logging
import pwd
import time
+import sys
from ipa.ipautil import *
import service
@@ -149,7 +150,7 @@ class RadiusInstance(service.Service):
retry += 1
if retry > 15:
print "Error timed out waiting for kadmin to finish operations\n"
- os.exit()
+ sys.exit(1)
try:
pent = pwd.getpwnam(RADIUS_USER)