Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
# 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, either version 3 of the License, or # (at your option) any later version. # # 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, see <http://www.gnu.org/licenses/>. #
# Autobind modes
# The service name as stored in cn=masters,cn=ipa,cn=etc. In the tuple # the first value is the *nix service name, the second the start order. 'KDC':('krb5kdc', 10), 'KPASSWD':('kadmin', 20), 'DNS':('named', 30), 'MEMCACHE':('ipa_memcached', 39), 'HTTP':('httpd', 40), 'CA':('%sd' % dogtag.configured_constants().PKI_INSTANCE_NAME, 50), 'ADTRUST':('smb', 60), 'EXTID':('winbind', 70) }
root_logger.debug(message) output_fd.write(message) output_fd.write("\n")
self.service_name = service_name self.service_desc = service_desc self.service = ipaservices.service(service_name) self.steps = [] self.output_fd = sys.stdout self.dm_password = dm_password self.ldapi = ldapi self.autobind = autobind
self.fqdn = socket.gethostname() self.admin_conn = None
if sstore: self.sstore = sstore else: self.sstore = sysrestore.StateFile('/var/lib/ipa/sysrestore')
self.realm = None self.suffix = DN() self.principal = None self.dercert = None
# If DM password is provided, we use it # If autobind was requested, attempt autobind when root and ldapi # If autobind was disabled or not succeeded, go with GSSAPI # LDAPI can be used with either autobind or GSSAPI # LDAPI requires realm to be set try: if self.ldapi: if not self.realm: raise errors.NotFound(reason="realm is missing for %s" % (self)) conn = ipaldap.IPAdmin(ldapi=self.ldapi, realm=self.realm) else: conn = ipaldap.IPAdmin(self.fqdn, port=389) if self.dm_password: conn.do_simple_bind(bindpw=self.dm_password) elif self.autobind in [AUTO, ENABLED]: if os.getegid() == 0 and self.ldapi: try: # autobind pw_name = pwd.getpwuid(os.geteuid()).pw_name conn.do_external_bind(pw_name) except errors.NotFound, e: if self.autobind == AUTO: # Fall back conn.do_sasl_gssapi_bind() else: # autobind was required and failed, raise # exception that it failed raise e else: conn.do_sasl_gssapi_bind() else: conn.do_sasl_gssapi_bind() except Exception, e: root_logger.debug("Could not connect to the Directory Server on %s: %s" % (self.fqdn, str(e))) raise
self.admin_conn = conn
self.admin_conn.unbind() self.admin_conn = None
pw_name = None fd = None path = ipautil.SHARE_DIR + ldif nologlist=[]
if sub_dict is not None: txt = ipautil.template_file(path, sub_dict) fd = ipautil.write_tmp_file(txt) path = fd.name
# do not log passwords if sub_dict.has_key('PASSWORD'): nologlist.append(sub_dict['PASSWORD']) if sub_dict.has_key('RANDOM_PASSWORD'): nologlist.append(sub_dict['RANDOM_PASSWORD'])
args = ["/usr/bin/ldapmodify", "-v", "-f", path]
# As we always connect to the local host, # use URI of admin connection if not self.admin_conn: self.ldap_connect() args += ["-H", self.admin_conn.ldap_uri]
auth_parms = [] if self.dm_password: [pw_fd, pw_name] = tempfile.mkstemp() os.write(pw_fd, self.dm_password) os.close(pw_fd) auth_parms = ["-x", "-D", "cn=Directory Manager", "-y", pw_name] else: # always try GSSAPI auth when not using DM password or not being root if os.getegid() != 0: auth_parms = ["-Y", "GSSAPI"]
args += auth_parms
try: try: ipautil.run(args, nolog=nologlist) except ipautil.CalledProcessError, e: root_logger.critical("Failed to load %s: %s" % (ldif, str(e))) finally: if pw_name: os.remove(pw_name)
if fd is not None: fd.close()
""" Used to move a principal entry created by kadmin.local from cn=kerberos to cn=services """
dn = DN(('krbprincipalname', principal), ('cn', self.realm), ('cn', 'kerberos'), self.suffix) try: entry = self.admin_conn.get_entry(dn) except errors.NotFound: # There is no service in the wrong location, nothing to do. # This can happen when installing a replica return None newdn = DN(('krbprincipalname', principal), ('cn', 'services'), ('cn', 'accounts'), self.suffix) hostdn = DN(('fqdn', self.fqdn), ('cn', 'computers'), ('cn', 'accounts'), self.suffix) self.admin_conn.delete_entry(entry) entry.dn = newdn classes = entry.get("objectclass") classes = classes + ["ipaobject", "ipaservice", "pkiuser"] entry["objectclass"] = list(set(classes)) entry["ipauniqueid"] = ['autogenerate'] entry["managedby"] = [hostdn] self.admin_conn.add_entry(entry) return newdn
""" Add a very basic IPA service.
The principal needs to be fully-formed: service/host@REALM """ if not self.admin_conn: self.ldap_connect()
dn = DN(('krbprincipalname', principal), ('cn', 'services'), ('cn', 'accounts'), self.suffix) hostdn = DN(('fqdn', self.fqdn), ('cn', 'computers'), ('cn', 'accounts'), self.suffix) entry = self.admin_conn.make_entry( dn, objectclass=[ "krbprincipal", "krbprincipalaux", "krbticketpolicyaux", "ipaobject", "ipaservice", "pkiuser"], krbprincipalname=[principal], ipauniqueid=['autogenerate'], managedby=[hostdn], ) self.admin_conn.add_entry(entry) return dn
""" Add a certificate to a service
This server cert should be in DER format. """
# add_cert_to_service() is relatively rare operation # we actually call it twice during ipa-server-install, for different # instances: ds and cs. Unfortunately, it may happen that admin # connection was created well before add_cert_to_service() is called # If there are other operations in between, it will become stale and # since we are using SimpleLDAPObject, not ReconnectLDAPObject, the # action will fail. Thus, explicitly disconnect and connect again. # Using ReconnectLDAPObject instead of SimpleLDAPObject was considered # but consequences for other parts of the framework are largely # unknown. if self.admin_conn: self.ldap_disconnect() self.ldap_connect()
dn = DN(('krbprincipalname', self.principal), ('cn', 'services'), ('cn', 'accounts'), self.suffix) entry = self.admin_conn.get_entry(dn) entry.setdefault('userCertificate', []).append(self.dercert) try: self.admin_conn.update_entry(entry) except Exception, e: root_logger.critical("Could not add certificate to service %s entry: %s" % (self.principal, str(e)))
return self.sstore.has_state(self.service_name)
self.output_fd = fd
self.service.stop(instance_name, capture_output=capture_output)
self.service.start(instance_name, capture_output=capture_output, wait=wait)
self.service.restart(instance_name, capture_output=capture_output, wait=wait)
return self.service.is_running()
self.service.install()
self.service.remove()
self.service.enable()
self.service.disable()
return self.service.is_enabled()
self.sstore.backup_state(self.service_name, key, value)
return self.sstore.restore_state(self.service_name, key)
return self.sstore.get_state(self.service_name, key)
print_msg(message, self.output_fd)
self.steps.append((message, method))
show_service_name=True, runtime=-1): """ Starts creation of the service.
Use start_message and end_message for explicit messages at the beggining / end of the process. Otherwise they are generated using the service description (or service name, if the description has not been provided).
Use show_service_name to include service name in generated descriptions. """
if start_message is None: # no other info than mandatory service_name provided, use that if self.service_desc is None: start_message = "Configuring %s" % self.service_name
# description should be more accurate than service name else: start_message = "Configuring %s" % self.service_desc if show_service_name: start_message = "%s (%s)" % (start_message, self.service_name)
if end_message is None: if self.service_desc is None: if show_service_name: end_message = "Done configuring %s." % self.service_name else: end_message = "Done." else: if show_service_name: end_message = "Done configuring %s (%s)." % ( self.service_desc, self.service_name) else: end_message = "Done configuring %s." % self.service_desc
if runtime > 0: plural='' est = time.localtime(runtime) if est.tm_min > 0: if est.tm_min > 1: plural = 's' if est.tm_sec > 0: self.print_msg('%s: Estimated time %d minute%s %d seconds' % (start_message, est.tm_min, plural, est.tm_sec)) else: self.print_msg('%s: Estimated time %d minute%s' % (start_message, est.tm_min, plural)) else: if est.tm_sec > 1: plural = 's' self.print_msg('%s: Estimated time %d second%s' % (start_message, est.tm_sec, plural)) else: self.print_msg(start_message)
step = 0 for (message, method) in self.steps: self.print_msg(" [%d/%d]: %s" % (step+1, len(self.steps), message)) s = datetime.datetime.now() method() e = datetime.datetime.now() d = e - s root_logger.debug(" duration: %d seconds" % d.seconds) step += 1
self.print_msg(end_message)
self.steps = []
assert isinstance(ldap_suffix, DN) self.disable() if not self.admin_conn: self.ldap_connect()
entry_name = DN(('cn', name), ('cn', fqdn), ('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), ldap_suffix) order = SERVICE_LIST[name][1] entry = self.admin_conn.make_entry( entry_name, objectclass=["nsContainer", "ipaConfigObject"], cn=[name], ipaconfigstring=[ "enabledService", "startOrder " + str(order)], )
try: self.admin_conn.add_entry(entry) except (errors.DuplicateEntry), e: root_logger.debug("failed to add %s Service startup entry" % name) raise e
self.gensvc_name = gensvc_name self.fqdn = fqdn self.dm_password = dm_password self.suffix = ldap_suffix self.realm = realm if not realm: self.ldapi = False
self.step("starting %s " % self.service_name, self.__start) self.step("configuring %s to start on boot" % self.service_name, self.__enable) self.start_creation("Configuring %s" % self.service_name)
self.backup_state("running", self.is_running()) self.restart()
self.enable() self.backup_state("enabled", self.is_enabled()) if self.gensvc_name == None: self.enable() else: self.ldap_enable(self.gensvc_name, self.fqdn, self.dm_password, self.suffix)
if self.is_configured(): self.print_msg("Unconfiguring %s" % self.service_name)
running = self.restore_state("running") enabled = not self.restore_state("enabled")
if not running is None and not running: self.stop() if not enabled is None and not enabled: self.disable() self.remove() |