Пример #1
0
 def __stop(self):
     self.backup_state("running", self.is_running())
     try:
         services.service('winbind', api).stop()
         self.stop()
     except Exception:
         pass
Пример #2
0
def stopped_service(service, instance_name=""):
    """
    Ensure that the specified service is stopped while the commands within
    this context are executed.

    Service is started at the end of the execution.
    """

    if instance_name:
        log_instance_name = "@{instance}".format(instance=instance_name)
    else:
        log_instance_name = ""

    root_logger.debug('Ensuring that service %s%s is not running while '
                      'the next set of commands is being executed.', service,
                      log_instance_name)

    service_obj = services.service(service)

    # Figure out if the service is running, if not, yield
    if not service_obj.is_running(instance_name):
        root_logger.debug('Service %s%s is not running, continue.', service,
                          log_instance_name)
        yield
    else:
        # Stop the service, do the required stuff and start it again
        root_logger.debug('Stopping %s%s.', service, log_instance_name)
        service_obj.stop(instance_name)
        try:
            yield
        finally:
            root_logger.debug('Starting %s%s.', service, log_instance_name)
            service_obj.start(instance_name)
Пример #3
0
    def __init__(self, service_name, service_desc=None, sstore=None,
                 fstore=None, api=api, realm_name=None,
                 service_user=None, service_prefix=None,
                 keytab=None):
        self.service_name = service_name
        self.service_desc = service_desc
        self.service = services.service(service_name, api)
        self.steps = []
        self.output_fd = sys.stdout

        self.fqdn = socket.gethostname()

        if sstore:
            self.sstore = sstore
        else:
            self.sstore = sysrestore.StateFile(paths.SYSRESTORE)

        if fstore:
            self.fstore = fstore
        else:
            self.fstore = sysrestore.FileStore(paths.SYSRESTORE)

        self.realm = realm_name
        self.suffix = DN()
        self.service_prefix = service_prefix
        self.keytab = keytab
        self.dercert = None
        self.api = api
        self.service_user = service_user
        self.keytab_user = service_user
        self.dm_password = None  # silence pylint
        self.promote = False
Пример #4
0
    def __init__(self, service_name, service_desc=None, sstore=None,
                 dm_password=None, ldapi=True, autobind=ipaldap.AUTOBIND_AUTO,
                 start_tls=False):
        self.service_name = service_name
        self.service_desc = service_desc
        self.service = services.service(service_name)
        self.steps = []
        self.output_fd = sys.stdout
        self.dm_password = dm_password
        self.ldapi = ldapi
        self.autobind = autobind
        self.start_tls = start_tls

        self.fqdn = socket.gethostname()
        self.admin_conn = None

        if sstore:
            self.sstore = sstore
        else:
            self.sstore = sysrestore.StateFile(paths.SYSRESTORE)

        self.realm = None
        self.suffix = DN()
        self.principal = None
        self.dercert = None
Пример #5
0
    def __init__(self, fstore=None, dm_password=None, api=api, ldapi=False,
                 start_tls=False, autobind=ipaldap.AUTOBIND_DISABLED):
        service.Service.__init__(
            self, "named",
            service_desc="DNS",
            dm_password=dm_password,
            ldapi=ldapi,
            autobind=autobind,
            start_tls=start_tls
        )
        self.dns_backup = DnsBackup(self)
        self.named_user = None
        self.domain = None
        self.host = None
        self.ip_addresses = []
        self.realm = None
        self.forwarders = None
        self.sub_dict = None
        self.reverse_zones = []
        self.dm_password = dm_password
        self.api = api
        self.named_regular = services.service('named-regular')

        if fstore:
            self.fstore = fstore
        else:
            self.fstore = sysrestore.FileStore(paths.SYSRESTORE)
Пример #6
0
def promote_sssd(host_name):
    sssdconfig = SSSDConfig.SSSDConfig()
    sssdconfig.import_config()
    domains = sssdconfig.list_active_domains()

    for name in domains:
        domain = sssdconfig.get_domain(name)
        try:
            hostname = domain.get_option('ipa_hostname')
            if hostname == host_name:
                break
        except SSSDConfig.NoOptionError:
            continue
    else:
        raise RuntimeError("Couldn't find IPA domain in sssd.conf")

    domain.set_option('ipa_server', host_name)
    domain.set_option('ipa_server_mode', True)
    sssdconfig.save_domain(domain)
    sssdconfig.write()

    sssd = services.service('sssd', api)
    try:
        sssd.restart()
    except CalledProcessError:
        logger.warning("SSSD service restart was unsuccessful.")
Пример #7
0
    def enable_and_start_oddjobd(self):
        oddjobd = services.service('oddjobd')
        self.sstore.backup_state('oddjobd', 'running', oddjobd.is_running())
        self.sstore.backup_state('oddjobd', 'enabled', oddjobd.is_enabled())

        try:
            oddjobd.enable()
            oddjobd.start()
        except Exception as e:
            root_logger.critical("Unable to start oddjobd: {0}".format(str(e)))
Пример #8
0
    def uninstall(self):
        if not self.is_configured():
            return

        self.print_msg("Unconfiguring %s" % self.service_name)

        running = self.restore_state("running")
        enabled = self.restore_state("enabled")

        # stop DNSSEC services before backing up kasp.db
        try:
            self.stop()
        except Exception:
            pass

        ods_exporter = services.service('ipa-ods-exporter')
        try:
            ods_exporter.stop()
        except Exception:
            pass

        # remove directive from ipa-dnskeysyncd, this server is not DNSSEC
        # master anymore
        installutils.set_directive(paths.SYSCONFIG_IPA_DNSKEYSYNCD,
                                   'ISMASTER', None,
                                   quotes=False, separator='=')

        if ipautil.file_exists(paths.OPENDNSSEC_KASP_DB):

            # force to export data
            ods_enforcerd = services.knownservices.ods_enforcerd
            cmd = [paths.IPA_ODS_EXPORTER, 'ipa-full-update']
            try:
                ipautil.run(cmd, runas=ods_enforcerd.get_user_name())
            except CalledProcessError:
                root_logger.debug("OpenDNSSEC database has not been updated")

            try:
                shutil.copy(paths.OPENDNSSEC_KASP_DB,
                            paths.IPA_KASP_DB_BACKUP)
            except IOError as e:
                root_logger.error(
                    "Unable to backup OpenDNSSEC database: %s", e)
            else:
                root_logger.info("OpenDNSSEC database backed up in %s",
                                 paths.IPA_KASP_DB_BACKUP)

        for f in [paths.OPENDNSSEC_CONF_FILE, paths.OPENDNSSEC_KASP_FILE,
                  paths.OPENDNSSEC_KASP_DB, paths.SYSCONFIG_ODS]:
            try:
                self.fstore.restore_file(f)
            except ValueError, error:
                root_logger.debug(error)
                pass
Пример #9
0
def check_timedate_services():
    """
    System may contain conflicting services used for time&date synchronization.
    As IPA server/client supports only chronyd, make sure that other services
    are not enabled to prevent conflicts.
    """
    for service in services.timedate_services:
        if service == 'chronyd':
            continue
        # Make sure that the service is not enabled
        instance = services.service(service, api)
        if instance.is_enabled() or instance.is_running():
            raise NTPConflictingService(
                    conflicting_service=instance.service_name)
Пример #10
0
    def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
        assert isinstance(dn, DN)
        self.obj.get_enabled_roles(entry_attrs)

        if 'ipalocation_location' in options:
            ipalocation = entry_attrs.get('ipalocation')
            if ipalocation:
                ipalocation = ipalocation[0]['idnsname']
            else:
                ipalocation = u''
            try:
                self.api.Command.dnsserver_mod(
                    keys[0],
                    setattr=[
                        u'idnsSubstitutionVariable;ipalocation={loc}'.format(
                            loc=ipalocation)
                    ]
                )
            except errors.EmptyModlist:
                pass
            except errors.NotFound:
                # server is not DNS server
                pass

        if 'ipalocation_location' or 'ipaserviceweight' in options:
            self.add_message(messages.ServiceRestartRequired(
                service=services.service('named', api).systemd_name,
                server=keys[0], ))

            result = self.api.Command.dns_update_system_records()
            if not result.get('value'):
                self.add_message(messages.AutomaticDNSRecordsUpdateFailed())
        self.obj.convert_location(entry_attrs, **options)

        ipalocation = entry_attrs.get('ipalocation_location', [None])[0]
        if ipalocation:
            servers_in_loc = self.api.Command.server_find(
                in_location=ipalocation, no_members=False)['result']
            dns_server_in_loc = False
            for server in servers_in_loc:
                if 'DNS server' in server.get('enabled_role_servrole', ()):
                    dns_server_in_loc = True
                    break
            if not dns_server_in_loc:
                self.add_message(messages.LocationWithoutDNSServer(
                    location=ipalocation
                ))

        return dn
Пример #11
0
def restore_forced_ntpd(statestore):
    """
    Restore from --force-ntpd installation and enable/start service that were
    disabled/stopped during installation
    """
    for service in services.timedate_services:
        if service == 'ntpd':
            continue
        if statestore.has_state(service):
            instance = services.service(service)
            enabled = statestore.restore_state(instance.service_name, 'enabled')
            running = statestore.restore_state(instance.service_name, 'running')
            if enabled:
                instance.enable()
            if running:
                instance.start()
Пример #12
0
    def uninstall(self):
        if self.is_configured():
            self.print_msg("Unconfiguring %s" % self.service_name)

        # Call restore_state so that we do not leave mess in the statestore
        # Otherwise this does nothing
        self.restore_state("running")
        self.restore_state("enabled")

        winbind = services.service("winbind")
        # Always try to stop and disable smb service, since we do not leave
        # working configuration after uninstall
        try:
            self.stop()
            self.disable()
            winbind.stop()
            winbind.disable()
        except Exception:
            pass

        # Since we do not guarantee restoring back to working samba state,
        # we should not restore smb.conf

        # Restore the state of affected selinux booleans
        boolean_states = {name: self.restore_state(name)
                          for name in SELINUX_BOOLEAN_SETTINGS}
        try:
            tasks.set_selinux_booleans(boolean_states)
        except ipapython.errors.SetseboolError as e:
            self.print_msg('WARNING: ' + str(e))

        # Remove samba's credentials cache
        krb5cc_samba = paths.KRB5CC_SAMBA
        installutils.remove_file(krb5cc_samba)

        # Remove samba's configuration file
        installutils.remove_file(self.smb_conf)

        # Remove samba's persistent and temporary tdb files
        tdb_files = [tdb_file for tdb_file in os.listdir(paths.SAMBA_DIR)
                                           if tdb_file.endswith(".tdb")]
        for tdb_file in tdb_files:
            installutils.remove_file(tdb_file)

        # Remove our keys from samba's keytab
        self.clean_samba_keytab()
Пример #13
0
def restore_forced_timeservices(statestore, skip_service='chronyd'):
    """
    Restore from installation and enable/start service that
    were disabled/stopped during installation
    """
    for service in services.timedate_services:
        if service == skip_service:
            continue
        if statestore.has_state(service):
            instance = services.service(service, api)
            enabled = statestore.restore_state(instance.service_name,
                                               'enabled')
            running = statestore.restore_state(instance.service_name,
                                               'running')
            if enabled:
                instance.enable()
            if running:
                instance.start()
Пример #14
0
 def __init__(self, fstore=None, api=api):
     super(BindInstance, self).__init__(
         "named",
         service_desc="DNS",
         fstore=fstore,
         api=api,
         service_user=constants.NAMED_USER,
         service_prefix=u'DNS',
         keytab=paths.NAMED_KEYTAB
     )
     self.dns_backup = DnsBackup(self)
     self.domain = None
     self.host = None
     self.ip_addresses = []
     self.forwarders = None
     self.sub_dict = None
     self.reverse_zones = []
     self.named_regular = services.service('named-regular', api)
Пример #15
0
    def __init__(self, service_name, service_desc=None, sstore=None):
        self.service_name = service_name
        self.service_desc = service_desc
        self.service = services.service(service_name)
        self.steps = []
        self.output_fd = sys.stdout

        self.fqdn = socket.gethostname()

        if sstore:
            self.sstore = sstore
        else:
            self.sstore = sysrestore.StateFile(paths.SYSRESTORE)

        self.realm = None
        self.suffix = DN()
        self.principal = None
        self.dercert = None
Пример #16
0
def check_timedate_services():
    """
    System may contain conflicting services used for time&date synchronization.
    As IPA server/client supports only ntpd, make sure that other services are
    not enabled to prevent conflicts. For example when both chronyd and ntpd
    are enabled, systemd would always start only chronyd to manage system
    time&date which would make IPA configuration of ntpd ineffective.

    Reference links:
      https://fedorahosted.org/freeipa/ticket/2974
      http://fedoraproject.org/wiki/Features/ChronyDefaultNTP
    """
    for service in services.timedate_services:
        if service == 'ntpd':
            continue
        # Make sure that the service is not enabled
        instance = services.service(service)
        if instance.is_enabled() or instance.is_running():
            raise NTPConflictingService(conflicting_service=instance.service_name)
Пример #17
0
    def __init__(self, fstore=None, api=api):
        service.Service.__init__(
            self, "named",
            service_desc="DNS"
        )
        self.dns_backup = DnsBackup(self)
        self.named_user = None
        self.domain = None
        self.host = None
        self.ip_addresses = []
        self.realm = None
        self.forwarders = None
        self.sub_dict = None
        self.reverse_zones = []
        self.api = api
        self.named_regular = services.service('named-regular')

        if fstore:
            self.fstore = fstore
        else:
            self.fstore = sysrestore.FileStore(paths.SYSRESTORE)
Пример #18
0
def force_ntpd(statestore):
    """
    Force ntpd configuration and disable and stop any other conflicting
    time&date service
    """
    for service in services.timedate_services:
        if service == 'ntpd':
            continue
        instance = services.service(service)
        enabled = instance.is_enabled()
        running = instance.is_running()

        if enabled or running:
            statestore.backup_state(instance.service_name, 'enabled', enabled)
            statestore.backup_state(instance.service_name, 'running', running)

            if running:
                instance.stop()

            if enabled:
                instance.disable()
Пример #19
0
    def __init__(self,
                 service_name,
                 service_desc=None,
                 sstore=None,
                 fstore=None,
                 api=api,
                 realm_name=None,
                 service_user=None,
                 service_prefix=None,
                 keytab=None):
        self.service_name = service_name
        self.service_desc = service_desc
        self.service = services.service(service_name, api)
        self.steps = []
        self.output_fd = sys.stdout

        self.fqdn = socket.gethostname()

        if sstore:
            self.sstore = sstore
        else:
            self.sstore = sysrestore.StateFile(paths.SYSRESTORE)

        if fstore:
            self.fstore = fstore
        else:
            self.fstore = sysrestore.FileStore(paths.SYSRESTORE)

        self.realm = realm_name
        self.suffix = DN()
        self.service_prefix = service_prefix
        self.keytab = keytab
        self.cert = None
        self.api = api
        self.service_user = service_user
        self.keytab_user = service_user
        self.dm_password = None  # silence pylint
        self.promote = False
Пример #20
0
    def run(self):
        api.bootstrap(in_server=True, confdir=paths.ETC_IPA)
        api.finalize()

        try:
            api.Backend.ldap2.connect()  # ensure DS is up

            # If required, enable Schema compat plugin on users/groups
            if self.options.enable_compat:
                try:
                    self._enable_compat_tree()
                except Exception as e:
                    raise ScriptError("Enabling Schema Compatibility plugin "
                                      "failed: {}".format(e))

            # Restart 389-ds and sssd
            logger.info("Restarting Directory Server")
            try:
                services.knownservices.dirsrv.restart()
            except Exception as e:
                raise ScriptError(
                    "Directory Server restart was unsuccessful: {}".format(e))

            logger.info("Restarting SSSD service")
            try:
                sssd = services.service('sssd', api)
                sssd.restart()
            except CalledProcessError as e:
                raise ScriptError(
                    "SSSD service restart was unsuccessful: {}".format(e))

        finally:
            if api.Backend.ldap2.isconnected():
                api.Backend.ldap2.disconnect()

        return 0
Пример #21
0
def install_check(standalone, api, replica, options, hostname):
    global ip_addresses
    global reverse_zones
    fstore = sysrestore.FileStore(paths.SYSRESTORE)

    if not ipautil.file_exists(paths.IPA_DNS_INSTALL):
        raise RuntimeError("Integrated DNS requires '%s' package" %
                           constants.IPA_DNS_PACKAGE_NAME)

    # when installing first DNS instance we need to check zone overlap
    if replica or standalone:
        already_enabled = api.Command.dns_is_enabled()['result']
    else:
        already_enabled = False

    if not already_enabled:
        domain = dnsutil.DNSName(util.normalize_zone(api.env.domain))
        print("Checking DNS domain %s, please wait ..." % domain)
        try:
            dnsutil.check_zone_overlap(domain, raise_on_error=False)
        except ValueError as e:
            if options.force or options.allow_zone_overlap:
                root_logger.warning("%s Please make sure that the domain is "
                                    "properly delegated to this IPA server.",
                                    e.message)
            else:
                raise e

    for reverse_zone in options.reverse_zones:
        try:
            dnsutil.check_zone_overlap(reverse_zone)
        except ValueError as e:
            if options.force or options.allow_zone_overlap:
                root_logger.warning(e.message)
            else:
                raise e

    if standalone:
        print("==============================================================================")
        print("This program will setup DNS for the FreeIPA Server.")
        print("")
        print("This includes:")
        print("  * Configure DNS (bind)")
        print("  * Configure SoftHSM (required by DNSSEC)")
        print("  * Configure ipa-dnskeysyncd (required by DNSSEC)")
        if options.dnssec_master:
            print("  * Configure ipa-ods-exporter (required by DNSSEC key master)")
            print("  * Configure OpenDNSSEC (required by DNSSEC key master)")
            print("  * Generate DNSSEC master key (required by DNSSEC key master)")
        elif options.disable_dnssec_master:
            print("  * Unconfigure ipa-ods-exporter")
            print("  * Unconfigure OpenDNSSEC")
            print("")
            print("No new zones will be signed without DNSSEC key master IPA server.")
            print("")
            print(("Please copy file from %s after uninstallation. This file is needed "
                   "on new DNSSEC key " % paths.IPA_KASP_DB_BACKUP))
            print("master server")
        print("")
        print("NOTE: DNSSEC zone signing is not enabled by default")
        print("")
        if options.dnssec_master:
            print("Plan carefully, replacing DNSSEC key master is not recommended")
            print("")
        print("")
        print("To accept the default shown in brackets, press the Enter key.")
        print("")

    if (options.dnssec_master and not options.unattended and not
        ipautil.user_input(
            "Do you want to setup this IPA server as DNSSEC key master?",
            False)):
        sys.exit("Aborted")
    elif (options.disable_dnssec_master and not options.unattended and not
          ipautil.user_input(
            "Do you want to disable current DNSSEC key master?",
            False)):
        sys.exit("Aborted")

    if options.disable_dnssec_master:
        _is_master()

    if options.disable_dnssec_master or options.dnssec_master:
        dnssec_zones = _find_dnssec_enabled_zones(api.Backend.ldap2)

    if options.disable_dnssec_master:
        if dnssec_zones and not options.force:
            raise RuntimeError(
                "Cannot disable DNSSEC key master, DNSSEC signing is still "
                "enabled for following zone(s):\n"
                "%s\n"
                "It is possible to move DNSSEC key master role to a different "
                "server by using --force option to skip this check.\n\n"
                "WARNING: You have to immediatelly copy kasp.db file to a new "
                "server and run command 'ipa-dns-install --dnssec-master "
                "--kasp-db'.\n"
                "Your DNS zones will become unavailable if you "
                "do not reinstall the DNSSEC key master role immediatelly." %
                ", ".join([str(zone) for zone in dnssec_zones]))

    elif options.dnssec_master:
        ods = opendnssecinstance.OpenDNSSECInstance(fstore)
        ods.realm = api.env.realm
        dnssec_masters = ods.get_masters()
        # we can reinstall current server if it is dnssec master
        if dnssec_masters and api.env.host not in dnssec_masters:
            print("DNSSEC key master(s):", u','.join(dnssec_masters))
            raise ScriptError(
                "Only one DNSSEC key master is supported in current version.")

        if options.kasp_db_file:
            dnskeysyncd = services.service('ipa-dnskeysyncd')

            if not dnskeysyncd.is_installed():
                raise RuntimeError("ipa-dnskeysyncd is not configured on this "
                                   "server, you cannot reuse OpenDNSSEC "
                                   "database (kasp.db file)")

            # check if replica can be the DNSSEC master
            cmd = [paths.IPA_DNSKEYSYNCD_REPLICA]
            environment = {
                "SOFTHSM2_CONF": paths.DNSSEC_SOFTHSM2_CONF,
            }

            # stop dnskeysyncd before test
            dnskeysyncd_running = dnskeysyncd.is_running()
            dnskeysyncd.stop()
            try:
                ipautil.run(cmd, env=environment,
                            runas=constants.ODS_USER,
                            suplementary_groups=[constants.NAMED_GROUP])
            except CalledProcessError as e:
                root_logger.debug("%s", e)
                raise RuntimeError("This IPA server cannot be promoted to "
                                   "DNSSEC master role because some keys were "
                                   "not replicated from the original "
                                   "DNSSEC master server")
            finally:
                if dnskeysyncd_running:
                    dnskeysyncd.start()
        elif dnssec_zones and not options.force:
            # some zones have --dnssec=true, make sure a user really want to
            # install new database
            raise RuntimeError(
                "DNSSEC signing is already enabled for following zone(s): %s\n"
                "Installation cannot continue without the OpenDNSSEC database "
                "file from the original DNSSEC master server.\n"
                "Please use option --kasp-db to specify location "
                "of the kasp.db file copied from the original "
                "DNSSEC master server.\n"
                "WARNING: Zones will become unavailable if you do not provide "
                "the original kasp.db file." %
                ", ".join([str(zone) for zone in dnssec_zones]))

    ip_addresses = get_server_ip_address(hostname, options.unattended,
                                         True, options.ip_addresses)

    util.network_ip_address_warning(ip_addresses)
    util.broadcast_ip_address_warning(ip_addresses)

    if not options.forward_policy:
        # user did not specify policy, derive it: default is 'first' but
        # if any of local IP addresses belongs to private ranges use 'only'
        options.forward_policy = 'first'
        for ip in ip_addresses:
            if dnsutil.inside_auto_empty_zone(dnsutil.DNSName(ip.reverse_dns)):
                options.forward_policy = 'only'
                root_logger.debug('IP address %s belongs to a private range, '
                                  'using forward policy only', ip)
                break

    if options.no_forwarders:
        options.forwarders = []
    elif options.forwarders or options.auto_forwarders:
        if not options.forwarders:
            options.forwarders = []
        if options.auto_forwarders:
            options.forwarders += resolver.get_default_resolver().nameservers
    elif standalone or not replica:
        options.forwarders = read_dns_forwarders()

    # test DNSSEC forwarders
    if options.forwarders:
        if (not bindinstance.check_forwarders(options.forwarders,
                                              root_logger)
                and not options.no_dnssec_validation):
            options.no_dnssec_validation = True
            print("WARNING: DNSSEC validation will be disabled")

    root_logger.debug("will use DNS forwarders: %s\n", options.forwarders)

    if not standalone:
        search_reverse_zones = False
    else:
        search_reverse_zones = True

    if not standalone and replica:
        reverse_zones_unattended_check = True
    else:
        reverse_zones_unattended_check = options.unattended

    reverse_zones = bindinstance.check_reverse_zones(
        ip_addresses, options.reverse_zones, options,
        reverse_zones_unattended_check, search_reverse_zones
    )

    if reverse_zones:
        print("Using reverse zone(s) %s" % ', '.join(reverse_zones))
Пример #22
0
 def __start(self):
     try:
         self.start()
         services.service('winbind', api).start()
     except Exception:
         logger.critical("CIFS services failed to start")
Пример #23
0
def restart_pki_ds():
    """Restart the CA DS instance to pick up schema changes
    """
    root_logger.info('Restarting CA DS')
    services.service('dirsrv').restart(SERVERID)
Пример #24
0
 def __start(self):
     srv = services.service(self.service_name, api)
     srv.start(self.serverid, ldapi=True)
     api.Backend.ldap2.connect()
Пример #25
0
def uninstall(fstore, statestore):
    RESTORE_FILES = [
        paths.SYSCONFIG_AUTOFS,
        paths.AUTOFS_LDAP_AUTH_CONF,
        paths.SYSCONFIG_NFS,
        paths.IDMAPD_CONF,
    ]
    STATES = ['autofs', 'rpcidmapd', 'rpcgssd']

    if not statestore.get_state('autofs', 'sssd'):
        tasks.disable_ldap_automount(statestore)

    if not any(fstore.has_file(f) for f in RESTORE_FILES) or not any(
        statestore.has_state(s) for s in STATES
    ):
        print("IPA automount is not configured on this system")
        return CLIENT_NOT_CONFIGURED

    print("Restoring configuration")

    for filepath in RESTORE_FILES:
        if fstore.has_file(filepath):
            fstore.restore_file(filepath)
    if statestore.has_state('autofs'):
        enabled = statestore.restore_state('autofs', 'enabled')
        running = statestore.restore_state('autofs', 'running')
        sssd = statestore.restore_state('autofs', 'sssd')
        autofs = services.knownservices.autofs
        if not enabled:
            autofs.disable()
        if not running:
            autofs.stop()
        if sssd:
            try:
                sssdconfig = SSSDConfig.SSSDConfig()
                sssdconfig.import_config()
                sssdconfig.deactivate_service('autofs')
                domains = sssdconfig.list_active_domains()
                for name in domains:
                    domain = sssdconfig.get_domain(name)
                    try:
                        provider = domain.get_option('id_provider')
                    except SSSDConfig.NoOptionError:
                        continue
                    if provider == "ipa":
                        domain.remove_option('ipa_automount_location')
                        sssdconfig.save_domain(domain)
                        domain.remove_provider('autofs')
                        sssdconfig.save_domain(domain)
                        break
                sssdconfig.write(paths.SSSD_CONF)
                sssd = services.service('sssd', api)
                sssd.restart()
                wait_for_sssd()
            except Exception as e:
                print('Unable to restore SSSD configuration: %s' % str(e))
                logger.debug(
                    'Unable to restore SSSD configuration: %s', str(e)
                )

    # rpcidmapd and rpcgssd are static units now
    if statestore.has_state('rpcidmapd'):
        statestore.delete_state('rpcidmapd', 'enabled')
        statestore.delete_state('rpcidmapd', 'running')
    if statestore.has_state('rpcgssd'):
        statestore.delete_state('rpcgssd', 'enabled')
        statestore.delete_state('rpcgssd', 'running')

    nfsutils = services.knownservices['nfs-utils']
    try:
        nfsutils.restart()
    except Exception as e:
        logger.error("Failed to restart nfs client services (%s)", str(e))
        return 1
    return 0
Пример #26
0
    def uninstall(self):
        if not self.is_configured():
            return

        self.print_msg("Unconfiguring %s" % self.service_name)

        running = self.restore_state("running")
        enabled = self.restore_state("enabled")

        # stop DNSSEC services before backing up kasp.db
        try:
            self.stop()
        except Exception:
            pass

        ods_exporter = services.service('ipa-ods-exporter', api)
        try:
            ods_exporter.stop()
        except Exception:
            pass

        # remove directive from ipa-dnskeysyncd, this server is not DNSSEC
        # master anymore
        installutils.set_directive(paths.SYSCONFIG_IPA_DNSKEYSYNCD,
                                   'ISMASTER',
                                   None,
                                   quotes=False,
                                   separator='=')

        restore_list = [
            paths.OPENDNSSEC_CONF_FILE, paths.OPENDNSSEC_KASP_FILE,
            paths.SYSCONFIG_ODS, paths.OPENDNSSEC_ZONELIST_FILE
        ]

        if ipautil.file_exists(paths.OPENDNSSEC_KASP_DB):

            # force to export data
            cmd = [paths.IPA_ODS_EXPORTER, 'ipa-full-update']
            try:
                self.print_msg("Exporting DNSSEC data before uninstallation")
                ipautil.run(cmd, runas=constants.ODS_USER)
            except CalledProcessError:
                root_logger.error("DNSSEC data export failed")

            try:
                shutil.copy(paths.OPENDNSSEC_KASP_DB, paths.IPA_KASP_DB_BACKUP)
            except IOError as e:
                root_logger.error(
                    "Unable to backup OpenDNSSEC database %s, "
                    "restore will be skipped: %s", paths.OPENDNSSEC_KASP_DB, e)
            else:
                root_logger.info("OpenDNSSEC database backed up in %s",
                                 paths.IPA_KASP_DB_BACKUP)
                # restore OpenDNSSEC's KASP DB only if backup succeeded
                # removing the file without backup could totally break DNSSEC
                restore_list.append(paths.OPENDNSSEC_KASP_DB)

        for f in restore_list:
            try:
                self.fstore.restore_file(f)
            except ValueError as error:
                root_logger.debug(error)

        self.restore_state("kasp_db_configured")  # just eat state

        # disabled by default, by ldap_enable()
        if enabled:
            self.enable()

        if running:
            self.restart()
Пример #27
0
def uninstall(fstore, statestore, options):
    # Shut down Samba services and disable them
    smb = services.service("smb", api)
    winbind = services.service("winbind", api)
    for svc in (smb, winbind):
        if svc.is_running():
            svc.stop()
        svc.disable()

    # Restore the state of affected selinux booleans
    boolean_states = {}
    for usecase in constants.SELINUX_BOOLEAN_SMBSERVICE:
        for name in usecase:
            boolean_states[name] = statestore.restore_state("selinux", name)

    if boolean_states:
        set_selinux_booleans(boolean_states, statestore, backup=False)

    # Remove samba's credentials cache
    ipautil.remove_ccache(ccache_path=paths.KRB5CC_SAMBA)

    # Remove samba's configuration file
    if fstore.has_file(paths.SMB_CONF):
        ipautil.remove_file(paths.SMB_CONF)
        fstore.restore_file(paths.SMB_CONF)

    # Remove samba's persistent and temporary tdb files
    # in /var/lib/samba and /var/lib/samba/private
    for smbpath in (paths.SAMBA_DIR, os.path.join(paths.SAMBA_DIR, "private"),
                    os.path.join(paths.SAMBA_DIR, "lock")):
        tdb_files = [
            os.path.join(smbpath, tdb_file) for tdb_file in os.listdir(smbpath)
            if tdb_file.endswith(".tdb")
        ]
        for tdb_file in tdb_files:
            ipautil.remove_file(tdb_file)

    # Remove our keys from samba's keytab
    if os.path.exists(paths.SAMBA_KEYTAB):
        try:
            ipautil.run([
                paths.IPA_RMKEYTAB,
                "--principal",
                api.env.smb_princ,
                "-k",
                paths.SAMBA_KEYTAB,
            ])
        except ipautil.CalledProcessError as e:
            if e.returncode != 5:
                logger.critical("Failed to remove old key for %s",
                                api.env.smb_princ)

    with use_api_as_principal(api.env.host_princ, paths.KRB5_KEYTAB):
        try:
            api.Command.service_del(api.env.smb_princ)
        except errors.VersionError as e:
            print("This client is incompatible: " + str(e))
        except errors.NotFound:
            logger.debug("No SMB service principal exists, OK to proceed")
        except errors.PublicError as e:
            logger.error(
                "Cannot connect to the server due to "
                "a generic error: %s",
                e,
            )
Пример #28
0
    def uninstall(self):
        if self.is_configured():
            self.print_msg("Unconfiguring web server")

        running = self.restore_state("running")
        enabled = self.restore_state("enabled")

        # Restore oddjobd to its original state
        oddjobd = services.service('oddjobd')

        if not self.sstore.restore_state('oddjobd', 'running'):
            try:
                oddjobd.stop()
            except Exception:
                pass

        if not self.sstore.restore_state('oddjobd', 'enabled'):
            try:
                oddjobd.disable()
            except Exception:
                pass

        self.stop_tracking_certificates()

        helper = self.restore_state('certmonger_ipa_helper')
        if helper:
            bus = dbus.SystemBus()
            obj = bus.get_object('org.fedorahosted.certmonger',
                                 '/org/fedorahosted/certmonger')
            iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
            path = iface.find_ca_by_nickname('IPA')
            if path:
                ca_obj = bus.get_object('org.fedorahosted.certmonger', path)
                ca_iface = dbus.Interface(ca_obj,
                                          'org.freedesktop.DBus.Properties')
                ca_iface.Set('org.fedorahosted.certmonger.ca',
                             'external-helper', helper)

        for f in [paths.HTTPD_IPA_CONF, paths.HTTPD_SSL_CONF, paths.HTTPD_NSS_CONF]:
            try:
                self.fstore.restore_file(f)
            except ValueError as error:
                root_logger.debug(error)

        installutils.remove_keytab(paths.IPA_KEYTAB)
        installutils.remove_ccache(ccache_path=paths.KRB5CC_HTTPD,
                                   run_as=HTTPD_USER)

        # Remove the configuration files we create
        installutils.remove_file(paths.HTTPD_IPA_REWRITE_CONF)
        installutils.remove_file(paths.HTTPD_IPA_CONF)
        installutils.remove_file(paths.HTTPD_IPA_PKI_PROXY_CONF)
        installutils.remove_file(paths.HTTPD_IPA_KDCPROXY_CONF_SYMLINK)
        installutils.remove_file(paths.HTTPD_IPA_KDCPROXY_CONF)

        # Restore SELinux boolean states
        boolean_states = {name: self.restore_state(name)
                          for name in SELINUX_BOOLEAN_SETTINGS}
        try:
            tasks.set_selinux_booleans(boolean_states)
        except ipapython.errors.SetseboolError as e:
            self.print_msg('WARNING: ' + str(e))

        if running:
            self.restart()

        # disabled by default, by ldap_enable()
        if enabled:
            self.enable()
Пример #29
0
def install_check(standalone, replica, options, hostname):
    global ip_addresses
    global dns_forwarders
    global reverse_zones
    fstore = sysrestore.FileStore(paths.SYSRESTORE)

    if not ipautil.file_exists(paths.IPA_DNS_INSTALL):
        raise RuntimeError("Integrated DNS requires '%s' package" %
                           constants.IPA_DNS_PACKAGE_NAME)

    if standalone:
        print "=============================================================================="
        print "This program will setup DNS for the FreeIPA Server."
        print ""
        print "This includes:"
        print "  * Configure DNS (bind)"
        print "  * Configure SoftHSM (required by DNSSEC)"
        print "  * Configure ipa-dnskeysyncd (required by DNSSEC)"
        if options.dnssec_master:
            print "  * Configure ipa-ods-exporter (required by DNSSEC key master)"
            print "  * Configure OpenDNSSEC (required by DNSSEC key master)"
            print "  * Generate DNSSEC master key (required by DNSSEC key master)"
        elif options.disable_dnssec_master:
            print "  * Unconfigure ipa-ods-exporter"
            print "  * Unconfigure OpenDNSSEC"
            print ""
            print "No new zones will be signed without DNSSEC key master IPA server."
            print ""
            print ("Please copy file from %s after uninstallation. This file is needed "
                   "on new DNSSEC key " % paths.IPA_KASP_DB_BACKUP)
            print "master server"
        print ""
        print "NOTE: DNSSEC zone signing is not enabled by default"
        print ""
        if options.dnssec_master:
            print "DNSSEC support is experimental!"
            print ""
            print "Plan carefully, replacing DNSSEC key master is not recommended"
            print ""
        print ""
        print "To accept the default shown in brackets, press the Enter key."
        print ""

    if (options.dnssec_master and not options.unattended and not
        ipautil.user_input(
            "Do you want to setup this IPA server as DNSSEC key master?",
            False)):
        sys.exit("Aborted")
    elif (options.disable_dnssec_master and not options.unattended and not
          ipautil.user_input(
            "Do you want to disable current DNSSEC key master?",
            False)):
        sys.exit("Aborted")

    # Check bind packages are installed
    if not bindinstance.check_inst(options.unattended):
        sys.exit("Aborting installation.")

    if options.disable_dnssec_master:
        _is_master()

    if options.disable_dnssec_master or options.dnssec_master:
        dnssec_zones = _find_dnssec_enabled_zones(api.Backend.ldap2)

    if options.disable_dnssec_master:
        if dnssec_zones and not options.force:
            raise RuntimeError(
                "Cannot disable DNSSEC key master, DNSSEC signing is still "
                "enabled for following zone(s):\n"
                "%s\n"
                "It is possible to move DNSSEC key master role to a different "
                "server by using --force option to skip this check.\n\n"
                "WARNING: You have to immediatelly copy kasp.db file to a new "
                "server and run command 'ipa-dns-install --dnssec-master "
                "--kasp-db'.\n"
                "Your DNS zones will become unavailable if you "
                "do not reinstall the DNSSEC key master role immediatelly." %
                ", ".join([str(zone) for zone in dnssec_zones]))

    elif options.dnssec_master:
        ods = opendnssecinstance.OpenDNSSECInstance(
            fstore, ldapi=True)
        ods.realm = api.env.realm
        dnssec_masters = ods.get_masters()
        # we can reinstall current server if it is dnssec master
        if dnssec_masters and api.env.host not in dnssec_masters:
            print "DNSSEC key master(s):", u','.join(dnssec_masters)
            sys.exit("Only one DNSSEC key master is supported in current "
                     "version.")

        if options.kasp_db_file:
            dnskeysyncd = services.service('ipa-dnskeysyncd')

            if not dnskeysyncd.is_installed():
                raise RuntimeError("ipa-dnskeysyncd is not configured on this "
                                   "server, you cannot reuse OpenDNSSEC "
                                   "database (kasp.db file)")

            # check if replica can be the DNSSEC master
            named = services.knownservices.named
            ods_enforcerd = services.knownservices.ods_enforcerd
            cmd = [paths.IPA_DNSKEYSYNCD_REPLICA]
            environment = {
                "SOFTHSM2_CONF": paths.DNSSEC_SOFTHSM2_CONF,
            }

            # stop dnskeysyncd before test
            dnskeysyncd_running = dnskeysyncd.is_running()
            dnskeysyncd.stop()
            try:
                ipautil.run(cmd, env=environment,
                            runas=ods_enforcerd.get_user_name(),
                            suplementary_groups=[named.get_group_name()])
            except CalledProcessError as e:
                root_logger.debug("%s", e)
                raise RuntimeError("This IPA server cannot be promoted to "
                                   "DNSSEC master role because some keys were "
                                   "not replicated from the original "
                                   "DNSSEC master server")
            finally:
                if dnskeysyncd_running:
                    dnskeysyncd.start()
        elif dnssec_zones and not options.force:
            # some zones have --dnssec=true, make sure a user really want to
            # install new database
            raise RuntimeError(
                "DNSSEC signing is already enabled for following zone(s): %s\n"
                "Installation cannot continue without the OpenDNSSEC database "
                "file from the original DNSSEC master server.\n"
                "Please use option --kasp-db to specify location "
                "of the kasp.db file copied from the original "
                "DNSSEC master server.\n"
                "WARNING: Zones will become unavailable if you do not provide "
                "the original kasp.db file." %
                ", ".join([str(zone) for zone in dnssec_zones]))

    ip_addresses = get_server_ip_address(
        hostname, fstore, options.unattended, True, options.ip_addresses)

    if options.no_forwarders:
        dns_forwarders = ()
    elif options.forwarders:
        dns_forwarders = options.forwarders
    elif standalone or not replica:
        dns_forwarders = read_dns_forwarders()

    # test DNSSEC forwarders
    if dns_forwarders:
        if (not bindinstance.check_forwarders(dns_forwarders, root_logger) and
                not options.no_dnssec_validation):
            options.no_dnssec_validation = True
            print "WARNING: DNSSEC validation will be disabled"

    root_logger.debug("will use dns_forwarders: %s\n", dns_forwarders)

    if not standalone:
        search_reverse_zones = False
    else:
        search_reverse_zones = True

    if not standalone and replica:
        reverse_zones_unattended_check = True
    else:
        reverse_zones_unattended_check = options.unattended

    reverse_zones = bindinstance.check_reverse_zones(
        ip_addresses, options.reverse_zones, options,
        reverse_zones_unattended_check, search_reverse_zones
    )

    if reverse_zones:
        print "Using reverse zone(s) %s" % ', '.join(reverse_zones)
Пример #30
0
def main():
    module = AnsibleModule(
        argument_spec = dict(
            servers=dict(required=True, type='list'),
            domain=dict(required=True),
            realm=dict(required=True),
            hostname=dict(required=True),
            basedn=dict(required=True),
            principal=dict(required=False),
            subject_base=dict(required=True),
            ca_enabled=dict(required=True, type='bool'),
            mkhomedir=dict(required=False, type='bool'),
            on_master=dict(required=False, type='bool'),
        ),
        supports_check_mode = True,
    )

    module._ansible_debug = True
    servers = module.params.get('servers')
    realm = module.params.get('realm')
    hostname = module.params.get('hostname')
    basedn = module.params.get('basedn')
    domain = module.params.get('domain')
    principal = module.params.get('principal')
    subject_base = module.params.get('subject_base')
    ca_enabled = module.params.get('ca_enabled')
    mkhomedir = module.params.get('mkhomedir')
    on_master = module.params.get('on_master')

    fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
    statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE)

    ###########################################################################

    os.environ['KRB5CCNAME'] = CCACHE_FILE
    
    class Object(object):
        pass
    options = Object()
    options.dns_updates = False
    options.all_ip_addresses = False
    options.ip_addresses = None
    options.request_cert = False
    options.hostname = hostname
    options.preserve_sssd = False
    options.on_master = False
    options.conf_ssh = True
    options.conf_sshd = True
    options.conf_sudo = True
    options.primary = False
    options.permit = False
    options.krb5_offline_passwords = False
    options.create_sshfp = True

    ##########################################################################

    # Create IPA NSS database
    try:
        create_ipa_nssdb()
    except ipautil.CalledProcessError as e:
        module.fail_json(msg="Failed to create IPA NSS database: %s" % e)

    # Get CA certificates from the certificate store
    try:
        ca_certs = get_certs_from_ldap(servers[0], basedn, realm,
                                       ca_enabled)
    except errors.NoCertificateError:
        if ca_enabled:
            ca_subject = DN(('CN', 'Certificate Authority'), subject_base)
        else:
            ca_subject = None
        ca_certs = certstore.make_compat_ca_certs(ca_certs, realm,
                                                  ca_subject)
    ca_certs_trust = [(c, n, certstore.key_policy_to_trust_flags(t, True, u))
                      for (c, n, t, u) in ca_certs]

    if hasattr(paths, "KDC_CA_BUNDLE_PEM"):
        x509.write_certificate_list(
            [c for c, n, t, u in ca_certs if t is not False],
            paths.KDC_CA_BUNDLE_PEM)
    if hasattr(paths, "CA_BUNDLE_PEM"):
        x509.write_certificate_list(
            [c for c, n, t, u in ca_certs if t is not False],
            paths.CA_BUNDLE_PEM)

    # Add the CA certificates to the IPA NSS database
    module.debug("Adding CA certificates to the IPA NSS database.")
    ipa_db = certdb.NSSDatabase(paths.IPA_NSSDB_DIR)
    for cert, nickname, trust_flags in ca_certs_trust:
        try:
            ipa_db.add_cert(cert, nickname, trust_flags)
        except CalledProcessError as e:
            module.fail_json(msg="Failed to add %s to the IPA NSS database." % nickname)

    # Add the CA certificates to the platform-dependant systemwide CA store
    tasks.insert_ca_certs_into_systemwide_ca_store(ca_certs)

    if not on_master:
        client_dns(servers[0], hostname, options)
        configure_certmonger(fstore, subject_base, realm, hostname,
                             options, ca_enabled)

    if hasattr(paths, "SSH_CONFIG_DIR"):
        ssh_config_dir = paths.SSH_CONFIG_DIR
    else:
        ssh_config_dir = services.knownservices.sshd.get_config_dir()
    update_ssh_keys(hostname, ssh_config_dir, options.create_sshfp)

    try:
        os.remove(CCACHE_FILE)
    except Exception:
        pass

    ##########################################################################

    # Name Server Caching Daemon. Disable for SSSD, use otherwise
    # (if installed)
    nscd = services.knownservices.nscd
    if nscd.is_installed():
        save_state(nscd, statestore)

        try:
            nscd_service_action = 'stop'
            nscd.stop()
        except Exception:
            module.warn("Failed to %s the %s daemon" %
                        (nscd_service_action, nscd.service_name))

        try:
            nscd.disable()
        except Exception:
            module.warn("Failed to disable %s daemon. Disable it manually." %
                        nscd.service_name)

    nslcd = services.knownservices.nslcd
    if nslcd.is_installed():
        save_state(nslcd, statestore)

    retcode, conf = (0, None)

    ##########################################################################

    # Modify nsswitch/pam stack
    tasks.modify_nsswitch_pam_stack(sssd=True,
                                    mkhomedir=mkhomedir,
                                    statestore=statestore)

    module.log("SSSD enabled")

    argspec = inspect.getargspec(services.service)
    if len(argspec.args) > 1:
        sssd = services.service('sssd', api)
    else:
        sssd = services.service('sssd')
    try:
        sssd.restart()
    except CalledProcessError:
        module.warn("SSSD service restart was unsuccessful.")

    try:
        sssd.enable()
    except CalledProcessError as e:
        module.warn(
            "Failed to enable automatic startup of the SSSD daemon: "
            "%s", e)

    if configure_openldap_conf(fstore, basedn, servers):
        module.log("Configured /etc/openldap/ldap.conf")
    else:
        module.log("Failed to configure /etc/openldap/ldap.conf")

    # Check that nss is working properly
    if not on_master:
        user = principal
        if user is None or user == "":
            user = "******" % domain
            module.log("Principal is not set when enrolling with OTP"
                       "; using principal '%s' for 'getent passwd'" % user)
        elif '@' not in user:
            user = "******" % (user, domain)
        n = 0
        found = False
        # Loop for up to 10 seconds to see if nss is working properly.
        # It can sometimes take a few seconds to connect to the remote
        # provider.
        # Particulary, SSSD might take longer than 6-8 seconds.
        while n < 10 and not found:
            try:
                ipautil.run(["getent", "passwd", user])
                found = True
            except Exception as e:
                time.sleep(1)
                n = n + 1

        if not found:
            module.fail_json(msg="Unable to find '%s' user with 'getent "
                             "passwd %s'!" % (user.split("@")[0], user))
            if conf:
                module.log("Recognized configuration: %s" % conf)
            else:
                module.fail_json(msg=
                                 "Unable to reliably detect "
                                 "configuration. Check NSS setup manually.")

            try:
                hardcode_ldap_server(servers)
            except Exception as e:
                module.fail_json(msg="Adding hardcoded server name to "
                                 "/etc/ldap.conf failed: %s" % str(e))

    ##########################################################################

    module.exit_json(changed=True,
                     ca_enabled_ra=ca_enabled)
Пример #31
0
def restart_pki_ds():
    """Restart the CA DS instance to pick up schema changes
    """
    root_logger.info('Restarting CA DS')
    services.service('dirsrv').restart(SERVERID)
Пример #32
0
 def __start(self):
     services.service(self.service_name).start(self.serverid, ldapi=True)
Пример #33
0
 def __start(self):
     try:
         self.start()
         services.service('winbind').start()
     except:
         root_logger.critical("CIFS services failed to start")
Пример #34
0
    def uninstall(self):
        if not self.is_configured():
            return

        self.print_msg("Unconfiguring %s" % self.service_name)

        running = self.restore_state("running")
        enabled = self.restore_state("enabled")

        # stop DNSSEC services before backing up kasp.db
        try:
            self.stop()
        except Exception:
            pass

        ods_exporter = services.service('ipa-ods-exporter')
        try:
            ods_exporter.stop()
        except Exception:
            pass

        # remove directive from ipa-dnskeysyncd, this server is not DNSSEC
        # master anymore
        installutils.set_directive(paths.SYSCONFIG_IPA_DNSKEYSYNCD,
                                   'ISMASTER', None,
                                   quotes=False, separator='=')

        restore_list = [paths.OPENDNSSEC_CONF_FILE, paths.OPENDNSSEC_KASP_FILE,
                        paths.SYSCONFIG_ODS, paths.OPENDNSSEC_ZONELIST_FILE]

        if ipautil.file_exists(paths.OPENDNSSEC_KASP_DB):

            # force to export data
            ods_enforcerd = services.knownservices.ods_enforcerd
            cmd = [paths.IPA_ODS_EXPORTER, 'ipa-full-update']
            try:
                self.print_msg("Exporting DNSSEC data before uninstallation")
                ipautil.run(cmd, runas=constants.ODS_USER)
            except CalledProcessError:
                root_logger.error("DNSSEC data export failed")

            try:
                shutil.copy(paths.OPENDNSSEC_KASP_DB,
                            paths.IPA_KASP_DB_BACKUP)
            except IOError as e:
                root_logger.error(
                    "Unable to backup OpenDNSSEC database %s, "
                    "restore will be skipped: %s", paths.OPENDNSSEC_KASP_DB, e)
            else:
                root_logger.info("OpenDNSSEC database backed up in %s",
                                 paths.IPA_KASP_DB_BACKUP)
                # restore OpenDNSSEC's KASP DB only if backup succeeded
                # removing the file without backup could totally break DNSSEC
                restore_list.append(paths.OPENDNSSEC_KASP_DB)

        for f in restore_list:
            try:
                self.fstore.restore_file(f)
            except ValueError as error:
                root_logger.debug(error)

        self.restore_state("kasp_db_configured")  # just eat state

        # disabled by default, by ldap_enable()
        if enabled:
            self.enable()

        if running:
            self.restart()
Пример #35
0
    def uninstall(self):
        if self.is_configured():
            self.print_msg("Unconfiguring web server")

        running = self.restore_state("running")
        enabled = self.restore_state("enabled")

        # Restore oddjobd to its original state
        oddjobd = services.service('oddjobd')

        if not self.sstore.restore_state('oddjobd', 'running'):
            try:
                oddjobd.stop()
            except Exception:
                pass

        if not self.sstore.restore_state('oddjobd', 'enabled'):
            try:
                oddjobd.disable()
            except Exception:
                pass

        self.stop_tracking_certificates()

        helper = self.restore_state('certmonger_ipa_helper')
        if helper:
            bus = dbus.SystemBus()
            obj = bus.get_object('org.fedorahosted.certmonger',
                                 '/org/fedorahosted/certmonger')
            iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
            path = iface.find_ca_by_nickname('IPA')
            if path:
                ca_obj = bus.get_object('org.fedorahosted.certmonger', path)
                ca_iface = dbus.Interface(ca_obj,
                                          'org.freedesktop.DBus.Properties')
                ca_iface.Set('org.fedorahosted.certmonger.ca',
                             'external-helper', helper)

        for f in [
                paths.HTTPD_IPA_CONF, paths.HTTPD_SSL_CONF,
                paths.HTTPD_NSS_CONF
        ]:
            try:
                self.fstore.restore_file(f)
            except ValueError as error:
                root_logger.debug(error)

        installutils.remove_keytab(self.keytab)
        installutils.remove_ccache(ccache_path=paths.KRB5CC_HTTPD,
                                   run_as=self.service_user)

        # Remove the configuration files we create
        installutils.remove_file(paths.HTTPD_IPA_REWRITE_CONF)
        installutils.remove_file(paths.HTTPD_IPA_CONF)
        installutils.remove_file(paths.HTTPD_IPA_PKI_PROXY_CONF)
        installutils.remove_file(paths.HTTPD_IPA_KDCPROXY_CONF_SYMLINK)
        installutils.remove_file(paths.HTTPD_IPA_KDCPROXY_CONF)
        tasks.remove_httpd_service_ipa_conf()

        # Restore SELinux boolean states
        boolean_states = {
            name: self.restore_state(name)
            for name in SELINUX_BOOLEAN_SETTINGS
        }
        try:
            tasks.set_selinux_booleans(boolean_states)
        except ipapython.errors.SetseboolError as e:
            self.print_msg('WARNING: ' + str(e))

        if running:
            self.restart()

        # disabled by default, by ldap_enable()
        if enabled:
            self.enable()
Пример #36
0
 def __start(self):
     srv = services.service(self.service_name, api)
     srv.start(self.serverid, ldapi=True)
     api.Backend.ldap2.connect()
Пример #37
0
    def uninstall(self):
        if self.is_configured():
            self.print_msg("Unconfiguring web server")

        running = self.restore_state("running")
        enabled = self.restore_state("enabled")

        # Restore oddjobd to its original state
        oddjobd = services.service('oddjobd', api)

        if not self.sstore.restore_state('oddjobd', 'running'):
            try:
                oddjobd.stop()
            except Exception:
                pass

        if not self.sstore.restore_state('oddjobd', 'enabled'):
            try:
                oddjobd.disable()
            except Exception:
                pass

        self.stop_tracking_certificates()

        helper = self.restore_state('certmonger_ipa_helper')
        if helper:
            bus = dbus.SystemBus()
            obj = bus.get_object('org.fedorahosted.certmonger',
                                 '/org/fedorahosted/certmonger')
            iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
            path = iface.find_ca_by_nickname('IPA')
            if path:
                ca_obj = bus.get_object('org.fedorahosted.certmonger', path)
                ca_iface = dbus.Interface(ca_obj,
                                          'org.freedesktop.DBus.Properties')
                ca_iface.Set('org.fedorahosted.certmonger.ca',
                             'external-helper', helper)

        for f in [paths.HTTPD_IPA_CONF, paths.HTTPD_SSL_CONF,
                  paths.HTTPD_SSL_SITE_CONF, paths.HTTPD_NSS_CONF]:
            try:
                self.fstore.restore_file(f)
            except ValueError as error:
                logger.debug("%s", error)

        # Remove the configuration files we create
        installutils.remove_keytab(self.keytab)
        remove_files = [
            paths.HTTP_CCACHE,
            paths.HTTPD_CERT_FILE,
            paths.HTTPD_KEY_FILE,
            paths.HTTPD_PASSWD_FILE_FMT.format(host=api.env.host),
            paths.HTTPD_IPA_REWRITE_CONF,
            paths.HTTPD_IPA_CONF,
            paths.HTTPD_IPA_PKI_PROXY_CONF,
            paths.HTTPD_IPA_KDCPROXY_CONF_SYMLINK,
            paths.HTTPD_IPA_KDCPROXY_CONF,
            paths.GSSPROXY_CONF,
            paths.GSSAPI_SESSION_KEY,
            paths.HTTPD_PASSWORD_CONF,
            paths.SYSTEMD_SYSTEM_HTTPD_IPA_CONF,
        ]
        # NSS DB backups
        remove_files.extend(
            glob.glob(os.path.join(paths.HTTPD_ALIAS_DIR, '*.ipasave'))
        )
        if paths.HTTPD_IPA_WSGI_MODULES_CONF is not None:
            remove_files.append(paths.HTTPD_IPA_WSGI_MODULES_CONF)

        for filename in remove_files:
            installutils.remove_file(filename)

        try:
            os.rmdir(paths.SYSTEMD_SYSTEM_HTTPD_D_DIR)
        except OSError as e:
            if e.errno not in {errno.ENOENT, errno.ENOTEMPTY}:
                logger.error(
                    "Failed to remove directory %s",
                    paths.SYSTEMD_SYSTEM_HTTPD_D_DIR
                )

        # Restore SELinux boolean states
        boolean_states = {name: self.restore_state(name)
                          for name in constants.SELINUX_BOOLEAN_HTTPD}
        try:
            tasks.set_selinux_booleans(boolean_states)
        except ipapython.errors.SetseboolError as e:
            self.print_msg('WARNING: ' + str(e))

        if running:
            self.restart()

        # disabled by default, by ldap_enable()
        if enabled:
            self.enable()
Пример #38
0
    def run(self):
        options = self.options
        super(Restore, self).run()

        self.backup_dir = self.args[0]
        if not os.path.isabs(self.backup_dir):
            self.backup_dir = os.path.join(paths.IPA_BACKUP_DIR, self.backup_dir)

        self.log.info("Preparing restore from %s on %s",
                      self.backup_dir, constants.FQDN)

        self.header = os.path.join(self.backup_dir, 'header')

        try:
            self.read_header()
        except IOError as e:
            raise admintool.ScriptError("Cannot read backup metadata: %s" % e)

        if options.data_only:
            restore_type = 'DATA'
        else:
            restore_type = self.backup_type

        # These checks would normally be in the validate method but
        # we need to know the type of backup we're dealing with.
        if restore_type == 'FULL':
            if options.online:
                raise admintool.ScriptError(
                    "File restoration cannot be done online")
            if options.instance or options.backend:
                raise admintool.ScriptError(
                    "Restore must be in data-only mode when restoring a "
                    "specific instance or backend")
        else:
            installutils.check_server_configuration()

            self.init_api()

            if options.instance:
                instance_dir = (paths.VAR_LIB_SLAPD_INSTANCE_DIR_TEMPLATE %
                                options.instance)
                if not os.path.exists(instance_dir):
                    raise admintool.ScriptError(
                        "Instance %s does not exist" % options.instance)

                self.instances = [options.instance]

            if options.backend:
                for instance in self.instances:
                    db_dir = (paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
                              (instance, options.backend))
                    if os.path.exists(db_dir):
                        break
                else:
                    raise admintool.ScriptError(
                        "Backend %s does not exist" % options.backend)

                self.backends = [options.backend]

            for instance, backend in itertools.product(self.instances,
                                                       self.backends):
                db_dir = (paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
                          (instance, backend))
                if os.path.exists(db_dir):
                    break
            else:
                raise admintool.ScriptError(
                    "Cannot restore a data backup into an empty system")

        self.log.info("Performing %s restore from %s backup" %
                      (restore_type, self.backup_type))

        if self.backup_host != constants.FQDN:
            raise admintool.ScriptError(
                "Host name %s does not match backup name %s" %
                (constants.FQDN, self.backup_host))

        if self.backup_ipa_version != str(version.VERSION):
            self.log.warning(
                "Restoring data from a different release of IPA.\n"
                "Data is version %s.\n"
                "Server is running %s." %
                (self.backup_ipa_version, str(version.VERSION)))
            if (not options.unattended and
                    not user_input("Continue to restore?", False)):
                raise admintool.ScriptError("Aborted")

        create_ds_user()
        pent = pwd.getpwnam(DS_USER)

        # Temporary directory for decrypting files before restoring
        self.top_dir = tempfile.mkdtemp("ipa")
        os.chown(self.top_dir, pent.pw_uid, pent.pw_gid)
        os.chmod(self.top_dir, 0o750)
        self.dir = os.path.join(self.top_dir, "ipa")
        os.mkdir(self.dir, 0o750)

        os.chown(self.dir, pent.pw_uid, pent.pw_gid)

        cwd = os.getcwd()
        try:
            dirsrv = services.knownservices.dirsrv

            self.extract_backup(options.gpg_keyring)

            if restore_type == 'FULL':
                self.restore_default_conf()
                self.init_api(confdir=self.dir + paths.ETC_IPA)

            databases = []
            for instance in self.instances:
                for backend in self.backends:
                    database = (instance, backend)
                    ldiffile = os.path.join(self.dir, '%s-%s.ldif' % database)
                    if os.path.exists(ldiffile):
                        databases.append(database)

            if options.instance:
                for instance, backend in databases:
                    if instance == options.instance:
                        break
                else:
                    raise admintool.ScriptError(
                        "Instance %s not found in backup" % options.instance)

            if options.backend:
                for instance, backend in databases:
                    if backend == options.backend:
                        break
                else:
                    raise admintool.ScriptError(
                        "Backend %s not found in backup" % options.backend)

            # Big fat warning
            if  (not options.unattended and
                not user_input("Restoring data will overwrite existing live data. Continue to restore?", False)):
                raise admintool.ScriptError("Aborted")

            self.log.info(
                "Each master will individually need to be re-initialized or")
            self.log.info(
                "re-created from this one. The replication agreements on")
            self.log.info(
                "masters running IPA 3.1 or earlier will need to be manually")
            self.log.info(
                "re-enabled. See the man page for details.")

            self.log.info("Disabling all replication.")
            self.disable_agreements()

            if restore_type != 'FULL':
                if not options.online:
                    self.log.info('Stopping Directory Server')
                    dirsrv.stop(capture_output=False)
                else:
                    self.log.info('Starting Directory Server')
                    dirsrv.start(capture_output=False)
            else:
                self.log.info('Stopping IPA services')
                (stdout, stderr, rc) = run(['ipactl', 'stop'], raiseonerr=False)
                if rc not in [0, 6]:
                    self.log.warn('Stopping IPA failed: %s' % stderr)

                self.restore_selinux_booleans()


            # We do either a full file restore or we restore data.
            if restore_type == 'FULL':
                if 'CA' in self.backup_services:
                    create_ca_user()
                self.cert_restore_prepare()
                self.file_restore(options.no_logs)
                self.cert_restore()
                if 'CA' in self.backup_services:
                    self.__create_dogtag_log_dirs()

            # Always restore the data from ldif
            # If we are restoring PKI-IPA then we need to restore the
            # userRoot backend in it and the main IPA instance. If we
            # have a unified instance we need to restore both userRoot and
            # ipaca.
            for instance, backend in databases:
                self.ldif2db(instance, backend, online=options.online)

            if restore_type != 'FULL':
                if not options.online:
                    self.log.info('Starting Directory Server')
                    dirsrv.start(capture_output=False)
            else:
                # restore access controll configuration
                auth_backup_path = os.path.join(paths.VAR_LIB_IPA, 'auth_backup')
                if os.path.exists(auth_backup_path):
                    tasks.restore_auth_configuration(auth_backup_path)
                # explicitly enable then disable the pki tomcatd service to
                # re-register its instance. FIXME, this is really wierd.
                services.knownservices.pki_tomcatd.enable()
                services.knownservices.pki_tomcatd.disable()

                self.log.info('Starting IPA services')
                run(['ipactl', 'start'])
                self.log.info('Restarting SSSD')
                sssd = services.service('sssd')
                sssd.restart()
                http = httpinstance.HTTPInstance()
                http.remove_httpd_ccache()
        finally:
            try:
                os.chdir(cwd)
            except Exception as e:
                self.log.error('Cannot change directory to %s: %s' % (cwd, e))
            shutil.rmtree(self.top_dir)
Пример #39
0
    def uninstall(self):
        if self.is_configured():
            self.print_msg("Unconfiguring web server")

        running = self.restore_state("running")
        enabled = self.restore_state("enabled")

        # Restore oddjobd to its original state
        oddjobd = services.service('oddjobd', api)

        if not self.sstore.restore_state('oddjobd', 'running'):
            try:
                oddjobd.stop()
            except Exception:
                pass

        if not self.sstore.restore_state('oddjobd', 'enabled'):
            try:
                oddjobd.disable()
            except Exception:
                pass

        self.stop_tracking_certificates()

        helper = self.restore_state('certmonger_ipa_helper')
        if helper:
            bus = dbus.SystemBus()
            obj = bus.get_object('org.fedorahosted.certmonger',
                                 '/org/fedorahosted/certmonger')
            iface = dbus.Interface(obj, 'org.fedorahosted.certmonger')
            path = iface.find_ca_by_nickname('IPA')
            if path:
                ca_obj = bus.get_object('org.fedorahosted.certmonger', path)
                ca_iface = dbus.Interface(ca_obj,
                                          'org.freedesktop.DBus.Properties')
                ca_iface.Set('org.fedorahosted.certmonger.ca',
                             'external-helper', helper)

        for f in [
                paths.HTTPD_IPA_CONF, paths.HTTPD_SSL_CONF,
                paths.HTTPD_SSL_SITE_CONF, paths.HTTPD_NSS_CONF
        ]:
            try:
                self.fstore.restore_file(f)
            except ValueError as error:
                logger.debug("%s", error)

        # Remove the configuration files we create
        installutils.remove_keytab(self.keytab)
        remove_files = [
            paths.HTTP_CCACHE,
            paths.HTTPD_CERT_FILE,
            paths.HTTPD_KEY_FILE,
            paths.HTTPD_PASSWD_FILE_FMT.format(host=api.env.host),
            paths.HTTPD_IPA_REWRITE_CONF,
            paths.HTTPD_IPA_CONF,
            paths.HTTPD_IPA_PKI_PROXY_CONF,
            paths.HTTPD_IPA_KDCPROXY_CONF_SYMLINK,
            paths.HTTPD_IPA_KDCPROXY_CONF,
            paths.GSSPROXY_CONF,
            paths.GSSAPI_SESSION_KEY,
            paths.HTTPD_PASSWORD_CONF,
            paths.SYSTEMD_SYSTEM_HTTPD_IPA_CONF,
        ]
        # NSS DB backups
        remove_files.extend(
            glob.glob(os.path.join(paths.HTTPD_ALIAS_DIR, '*.ipasave')))
        if paths.HTTPD_IPA_WSGI_MODULES_CONF is not None:
            remove_files.append(paths.HTTPD_IPA_WSGI_MODULES_CONF)

        for filename in remove_files:
            installutils.remove_file(filename)

        try:
            os.rmdir(paths.SYSTEMD_SYSTEM_HTTPD_D_DIR)
        except OSError as e:
            if e.errno not in {errno.ENOENT, errno.ENOTEMPTY}:
                logger.error("Failed to remove directory %s",
                             paths.SYSTEMD_SYSTEM_HTTPD_D_DIR)

        # Restore SELinux boolean states
        boolean_states = {
            name: self.restore_state(name)
            for name in constants.SELINUX_BOOLEAN_HTTPD
        }
        try:
            tasks.set_selinux_booleans(boolean_states)
        except ipapython.errors.SetseboolError as e:
            self.print_msg('WARNING: ' + str(e))

        if running:
            self.restart()

        # disabled by default, by ldap_enable()
        if enabled:
            self.enable()
Пример #40
0
 def __start(self):
     try:
         self.start()
         services.service('winbind').start()
     except:
         root_logger.critical("CIFS services failed to start")
Пример #41
0
 def __start(self):
     services.service(self.service_name).start(self.serverid, ldapi=True)
Пример #42
0
    def run(self):
        options = self.options
        super(Restore, self).run()

        self.backup_dir = self.args[0]
        if not os.path.isabs(self.backup_dir):
            self.backup_dir = os.path.join(paths.IPA_BACKUP_DIR, self.backup_dir)

        logger.info("Preparing restore from %s on %s",
                    self.backup_dir, FQDN)

        self.header = os.path.join(self.backup_dir, 'header')

        try:
            self.read_header()
        except IOError as e:
            raise admintool.ScriptError("Cannot read backup metadata: %s" % e)

        if options.data_only:
            restore_type = 'DATA'
        else:
            restore_type = self.backup_type

        # These checks would normally be in the validate method but
        # we need to know the type of backup we're dealing with.
        if restore_type == 'FULL':
            if options.online:
                raise admintool.ScriptError(
                    "File restoration cannot be done online")
            if options.instance or options.backend:
                raise admintool.ScriptError(
                    "Restore must be in data-only mode when restoring a "
                    "specific instance or backend")
        else:
            installutils.check_server_configuration()

            self.init_api()

            if options.instance:
                instance_dir = (paths.VAR_LIB_SLAPD_INSTANCE_DIR_TEMPLATE %
                                options.instance)
                if not os.path.exists(instance_dir):
                    raise admintool.ScriptError(
                        "Instance %s does not exist" % options.instance)

                self.instances = [options.instance]

            if options.backend:
                for instance in self.instances:
                    db_dir = (paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
                              (instance, options.backend))
                    if os.path.exists(db_dir):
                        break
                else:
                    raise admintool.ScriptError(
                        "Backend %s does not exist" % options.backend)

                self.backends = [options.backend]

            for instance, backend in itertools.product(self.instances,
                                                       self.backends):
                db_dir = (paths.SLAPD_INSTANCE_DB_DIR_TEMPLATE %
                          (instance, backend))
                if os.path.exists(db_dir):
                    break
            else:
                raise admintool.ScriptError(
                    "Cannot restore a data backup into an empty system")

        logger.info("Performing %s restore from %s backup",
                    restore_type, self.backup_type)

        if self.backup_host != FQDN:
            raise admintool.ScriptError(
                "Host name %s does not match backup name %s" %
                (FQDN, self.backup_host))

        if self.backup_ipa_version != str(version.VERSION):
            logger.warning(
                "Restoring data from a different release of IPA.\n"
                "Data is version %s.\n"
                "Server is running %s.",
                self.backup_ipa_version, str(version.VERSION))
            if (not options.unattended and
                    not user_input("Continue to restore?", False)):
                raise admintool.ScriptError("Aborted")

        pent = pwd.getpwnam(constants.DS_USER)

        # Temporary directory for decrypting files before restoring
        self.top_dir = tempfile.mkdtemp("ipa")
        os.chown(self.top_dir, pent.pw_uid, pent.pw_gid)
        os.chmod(self.top_dir, 0o750)
        self.dir = os.path.join(self.top_dir, "ipa")
        os.mkdir(self.dir)
        os.chmod(self.dir, 0o750)
        os.chown(self.dir, pent.pw_uid, pent.pw_gid)

        cwd = os.getcwd()

        logger.info("Temporary setting umask to 022")
        old_umask = os.umask(0o022)
        try:
            dirsrv = services.knownservices.dirsrv

            self.extract_backup(options.gpg_keyring)

            if restore_type == 'FULL':
                self.restore_default_conf()
                self.init_api(confdir=self.dir + paths.ETC_IPA)

            databases = []
            for instance in self.instances:
                for backend in self.backends:
                    database = (instance, backend)
                    ldiffile = os.path.join(self.dir, '%s-%s.ldif' % database)
                    if os.path.exists(ldiffile):
                        databases.append(database)

            if options.instance:
                for instance, backend in databases:
                    if instance == options.instance:
                        break
                else:
                    raise admintool.ScriptError(
                        "Instance %s not found in backup" % options.instance)

            if options.backend:
                for instance, backend in databases:
                    if backend == options.backend:
                        break
                else:
                    raise admintool.ScriptError(
                        "Backend %s not found in backup" % options.backend)

            # Big fat warning
            if  (not options.unattended and
                not user_input("Restoring data will overwrite existing live data. Continue to restore?", False)):
                raise admintool.ScriptError("Aborted")

            logger.info(
                "Each master will individually need to be re-initialized or")
            logger.info(
                "re-created from this one. The replication agreements on")
            logger.info(
                "masters running IPA 3.1 or earlier will need to be manually")
            logger.info(
                "re-enabled. See the man page for details.")

            logger.info("Disabling all replication.")
            self.disable_agreements()

            if restore_type != 'FULL':
                if not options.online:
                    logger.info('Stopping Directory Server')
                    dirsrv.stop(capture_output=False)
                else:
                    logger.info('Starting Directory Server')
                    dirsrv.start(capture_output=False)
            else:
                logger.info('Stopping IPA services')
                result = run([paths.IPACTL, 'stop'], raiseonerr=False)
                if result.returncode not in [0, 6]:
                    logger.warning('Stopping IPA failed: %s', result.error_log)

                self.restore_selinux_booleans()

            http = httpinstance.HTTPInstance()

            # We do either a full file restore or we restore data.
            if restore_type == 'FULL':
                self.remove_old_files()
                self.cert_restore_prepare()
                self.file_restore(options.no_logs)
                self.cert_restore()
                if 'CA' in self.backup_services:
                    self.__create_dogtag_log_dirs()

            # Always restore the data from ldif
            # We need to restore both userRoot and ipaca.
            for instance, backend in databases:
                self.ldif2db(instance, backend, online=options.online)

            if restore_type != 'FULL':
                if not options.online:
                    logger.info('Starting Directory Server')
                    dirsrv.start(capture_output=False)
            else:
                # restore access controll configuration
                auth_backup_path = os.path.join(paths.VAR_LIB_IPA, 'auth_backup')
                if os.path.exists(auth_backup_path):
                    tasks.restore_auth_configuration(auth_backup_path)
                # explicitly enable then disable the pki tomcatd service to
                # re-register its instance. FIXME, this is really wierd.
                services.knownservices.pki_tomcatd.enable()
                services.knownservices.pki_tomcatd.disable()

                logger.info('Restarting GSS-proxy')
                gssproxy = services.service('gssproxy', api)
                gssproxy.reload_or_restart()
                logger.info('Starting IPA services')
                run([paths.IPACTL, 'start'])
                logger.info('Restarting SSSD')
                sssd = services.service('sssd', api)
                sssd.restart()
                logger.info('Restarting oddjobd')
                oddjobd = services.service('oddjobd', api)
                if not oddjobd.is_enabled():
                    logger.info("Enabling oddjobd")
                    oddjobd.enable()
                oddjobd.start()
                http.remove_httpd_ccaches()
                # have the daemons pick up their restored configs
                run([paths.SYSTEMCTL, "--system", "daemon-reload"])
        finally:
            try:
                os.chdir(cwd)
            except Exception as e:
                logger.error('Cannot change directory to %s: %s', cwd, e)
            shutil.rmtree(self.top_dir)
            logger.info("Restoring umask to %s", old_umask)
            os.umask(old_umask)
Пример #43
0
def ipa_start(options):

    if not options.skip_version_check:
        version_check()
    else:
        print("Skipping version check")

    if os.path.isfile(tasks.get_svc_list_file()):
        emit_err("Existing service file detected!")
        emit_err("Assuming stale, cleaning and proceeding")
        # remove file with list of started services
        # This is ok as systemd will just skip services
        # that are already running and just return, so that the
        # stop() method of the base class will simply fill in the
        # service file again
        os.unlink(paths.SVC_LIST_FILE)

    dirsrv = services.knownservices.dirsrv
    try:
        print("Starting Directory Service")
        dirsrv.start(
            capture_output=get_capture_output("dirsrv", options.debug))
    except Exception as e:
        raise IpactlError("Failed to start Directory Service: " + str(e))

    try:
        svc_list = get_config(dirsrv)
    except Exception as e:
        emit_err("Failed to read data from service file: " + str(e))
        emit_err("Shutting down")

        if not options.ignore_service_failures:
            stop_dirsrv(dirsrv)

        if isinstance(e, IpactlError):
            # do not display any other error message
            raise IpactlError(rval=e.rval)
        else:
            raise IpactlError()

    if len(svc_list) == 0:
        # no service to start
        return

    for svc in svc_list:
        svchandle = services.service(svc, api=api)
        try:
            print("Starting %s Service" % svc)
            svchandle.start(
                capture_output=get_capture_output(svc, options.debug))
        except Exception:
            emit_err("Failed to start %s Service" % svc)
            # if ignore_service_failures is specified, skip rollback and
            # continue with the next service
            if options.ignore_service_failures:
                emit_err("Forced start, ignoring %s Service, "
                         "continuing normal operation" % svc)
                continue

            emit_err("Shutting down")
            stop_services(svc_list)
            stop_dirsrv(dirsrv)

            emit_err(MSG_HINT_IGNORE_SERVICE_FAILURE)
            raise IpactlError("Aborting ipactl")
Пример #44
0
def install_check(standalone, api, replica, options, hostname):
    global ip_addresses
    global reverse_zones
    fstore = sysrestore.FileStore(paths.SYSRESTORE)

    if not os.path.isfile(paths.IPA_DNS_INSTALL):
        raise RuntimeError("Integrated DNS requires '%s' package" %
                           constants.IPA_DNS_PACKAGE_NAME)

    # when installing first DNS instance we need to check zone overlap
    if replica or standalone:
        already_enabled = api.Command.dns_is_enabled()['result']
    else:
        already_enabled = False

    if not already_enabled:
        domain = dnsutil.DNSName(util.normalize_zone(api.env.domain))
        print("Checking DNS domain %s, please wait ..." % domain)
        try:
            dnsutil.check_zone_overlap(domain, raise_on_error=False)
        except ValueError as e:
            if options.force or options.allow_zone_overlap:
                logger.warning("%s Please make sure that the domain is "
                               "properly delegated to this IPA server.",
                               e)
            else:
                raise e

    for reverse_zone in options.reverse_zones:
        try:
            dnsutil.check_zone_overlap(reverse_zone)
        except ValueError as e:
            if options.force or options.allow_zone_overlap:
                logger.warning('%s', six.text_type(e))
            else:
                raise e

    if standalone:
        print("==============================================================================")
        print("This program will setup DNS for the FreeIPA Server.")
        print("")
        print("This includes:")
        print("  * Configure DNS (bind)")
        print("  * Configure SoftHSM (required by DNSSEC)")
        print("  * Configure ipa-dnskeysyncd (required by DNSSEC)")
        if options.dnssec_master:
            print("  * Configure ipa-ods-exporter (required by DNSSEC key master)")
            print("  * Configure OpenDNSSEC (required by DNSSEC key master)")
            print("  * Generate DNSSEC master key (required by DNSSEC key master)")
        elif options.disable_dnssec_master:
            print("  * Unconfigure ipa-ods-exporter")
            print("  * Unconfigure OpenDNSSEC")
            print("")
            print("No new zones will be signed without DNSSEC key master IPA server.")
            print("")
            print(("Please copy file from %s after uninstallation. This file is needed "
                   "on new DNSSEC key " % paths.IPA_KASP_DB_BACKUP))
            print("master server")
        print("")
        print("NOTE: DNSSEC zone signing is not enabled by default")
        print("")
        if options.dnssec_master:
            print("Plan carefully, replacing DNSSEC key master is not recommended")
            print("")
        print("")
        print("To accept the default shown in brackets, press the Enter key.")
        print("")

    if (options.dnssec_master and not options.unattended and not
        ipautil.user_input(
            "Do you want to setup this IPA server as DNSSEC key master?",
            False)):
        sys.exit("Aborted")
    elif (options.disable_dnssec_master and not options.unattended and not
          ipautil.user_input(
            "Do you want to disable current DNSSEC key master?",
            False)):
        sys.exit("Aborted")

    if options.disable_dnssec_master:
        _is_master()

    if options.disable_dnssec_master or options.dnssec_master:
        dnssec_zones = _find_dnssec_enabled_zones(api.Backend.ldap2)

    if options.disable_dnssec_master:
        if dnssec_zones and not options.force:
            raise RuntimeError(
                "Cannot disable DNSSEC key master, DNSSEC signing is still "
                "enabled for following zone(s):\n"
                "%s\n"
                "It is possible to move DNSSEC key master role to a different "
                "server by using --force option to skip this check.\n\n"
                "WARNING: You have to immediately copy kasp.db file to a new "
                "server and run command 'ipa-dns-install --dnssec-master "
                "--kasp-db'.\n"
                "Your DNS zones will become unavailable if you "
                "do not reinstall the DNSSEC key master role immediately." %
                ", ".join([str(zone) for zone in dnssec_zones]))

    elif options.dnssec_master:
        ods = opendnssecinstance.OpenDNSSECInstance(fstore)
        ods.realm = api.env.realm
        dnssec_masters = ods.get_masters()
        # we can reinstall current server if it is dnssec master
        if dnssec_masters and api.env.host not in dnssec_masters:
            print("DNSSEC key master(s):", u','.join(dnssec_masters))
            raise ScriptError(
                "Only one DNSSEC key master is supported in current version.")

        if options.kasp_db_file:
            dnskeysyncd = services.service('ipa-dnskeysyncd', api)

            if not dnskeysyncd.is_installed():
                raise RuntimeError("ipa-dnskeysyncd is not configured on this "
                                   "server, you cannot reuse OpenDNSSEC "
                                   "database (kasp.db file)")

            # check if replica can be the DNSSEC master
            cmd = [paths.IPA_DNSKEYSYNCD_REPLICA]
            environment = {
                "SOFTHSM2_CONF": paths.DNSSEC_SOFTHSM2_CONF,
            }

            # stop dnskeysyncd before test
            dnskeysyncd_running = dnskeysyncd.is_running()
            dnskeysyncd.stop()
            try:
                ipautil.run(cmd, env=environment,
                            runas=constants.ODS_USER,
                            suplementary_groups=[constants.NAMED_GROUP])
            except CalledProcessError as e:
                logger.debug("%s", e)
                raise RuntimeError("This IPA server cannot be promoted to "
                                   "DNSSEC master role because some keys were "
                                   "not replicated from the original "
                                   "DNSSEC master server")
            finally:
                if dnskeysyncd_running:
                    dnskeysyncd.start()
        elif dnssec_zones and not options.force:
            # some zones have --dnssec=true, make sure a user really want to
            # install new database
            raise RuntimeError(
                "DNSSEC signing is already enabled for following zone(s): %s\n"
                "Installation cannot continue without the OpenDNSSEC database "
                "file from the original DNSSEC master server.\n"
                "Please use option --kasp-db to specify location "
                "of the kasp.db file copied from the original "
                "DNSSEC master server.\n"
                "WARNING: Zones will become unavailable if you do not provide "
                "the original kasp.db file." %
                ", ".join([str(zone) for zone in dnssec_zones]))

    ip_addresses = get_server_ip_address(hostname, options.unattended,
                                         True, options.ip_addresses)

    util.no_matching_interface_for_ip_address_warning(ip_addresses)

    if not options.forward_policy:
        # user did not specify policy, derive it: default is 'first' but
        # if any of local IP addresses belongs to private ranges use 'only'
        options.forward_policy = 'first'
        for ip in ip_addresses:
            if dnsutil.inside_auto_empty_zone(dnsutil.DNSName(ip.reverse_dns)):
                options.forward_policy = 'only'
                logger.debug('IP address %s belongs to a private range, '
                             'using forward policy only', ip)
                break

    if options.no_forwarders:
        options.forwarders = []
    elif options.forwarders or options.auto_forwarders:
        if not options.forwarders:
            options.forwarders = []
        if options.auto_forwarders:
            options.forwarders += resolver.get_default_resolver().nameservers
    elif standalone or not replica:
        options.forwarders = read_dns_forwarders()

    # test DNSSEC forwarders
    if options.forwarders:
        if (not bindinstance.check_forwarders(options.forwarders)
                and not options.no_dnssec_validation):
            options.no_dnssec_validation = True
            print("WARNING: DNSSEC validation will be disabled")

    logger.debug("will use DNS forwarders: %s\n", options.forwarders)

    if not standalone:
        search_reverse_zones = False
    else:
        search_reverse_zones = True

    if not standalone and replica:
        reverse_zones_unattended_check = True
    else:
        reverse_zones_unattended_check = options.unattended

    reverse_zones = bindinstance.check_reverse_zones(
        ip_addresses, options.reverse_zones, options,
        reverse_zones_unattended_check, search_reverse_zones
    )

    if reverse_zones:
        print("Using reverse zone(s) %s" % ', '.join(reverse_zones))
Пример #45
0
def ipa_restart(options):
    if not options.skip_version_check:
        try:
            version_check()
        except Exception as e:
            try:
                ipa_stop(options)
            except Exception:
                # We don't care about errors that happened while stopping.
                # We need to raise the upgrade error.
                pass
            raise e
    else:
        print("Skipping version check")

    dirsrv = services.knownservices.dirsrv
    new_svc_list = []
    dirsrv_restart = True
    if not dirsrv.is_running():
        try:
            print("Starting Directory Service")
            dirsrv.start(
                capture_output=get_capture_output("dirsrv", options.debug))
            dirsrv_restart = False
        except Exception as e:
            raise IpactlError("Failed to start Directory Service: " + str(e))

    try:
        new_svc_list = get_config(dirsrv)
    except Exception as e:
        emit_err("Failed to read data from Directory Service: " + str(e))
        emit_err("Shutting down")
        try:
            dirsrv.stop(capture_output=False)
        except Exception:
            pass
        if isinstance(e, IpactlError):
            # do not display any other error message
            raise IpactlError(rval=e.rval)
        else:
            raise IpactlError()

    old_svc_list = []
    try:
        old_svc_list = get_config_from_file(rval=4)
    except Exception as e:
        emit_err("Failed to get service list from file: " + str(e))
        # fallback to what's in LDAP
        old_svc_list = new_svc_list

    # match service to start/stop
    svc_list = []
    for s in new_svc_list:
        if s in old_svc_list:
            svc_list.append(s)

    # remove commons
    for s in svc_list:
        if s in old_svc_list:
            old_svc_list.remove(s)
    for s in svc_list:
        if s in new_svc_list:
            new_svc_list.remove(s)

    if len(old_svc_list) != 0:
        # we need to definitely stop some services
        for svc in reversed(old_svc_list):
            svchandle = services.service(svc, api=api)
            try:
                print("Stopping %s Service" % svc)
                svchandle.stop(capture_output=False)
            except Exception:
                emit_err("Failed to stop %s Service" % svc)

    try:
        if dirsrv_restart:
            print("Restarting Directory Service")
            dirsrv.restart(
                capture_output=get_capture_output("dirsrv", options.debug))
    except Exception as e:
        emit_err("Failed to restart Directory Service: " + str(e))
        emit_err("Shutting down")

        if not options.ignore_service_failures:
            stop_services(reversed(svc_list))
            stop_dirsrv(dirsrv)

        raise IpactlError("Aborting ipactl")

    if len(svc_list) != 0:
        # there are services to restart
        for svc in svc_list:
            svchandle = services.service(svc, api=api)
            try:
                print("Restarting %s Service" % svc)
                svchandle.restart(
                    capture_output=get_capture_output(svc, options.debug))
            except Exception:
                emit_err("Failed to restart %s Service" % svc)
                # if ignore_service_failures is specified,
                # skip rollback and continue with the next service
                if options.ignore_service_failures:
                    emit_err("Forced restart, ignoring %s Service, "
                             "continuing normal operation" % svc)
                    continue

                emit_err("Shutting down")
                stop_services(svc_list)
                stop_dirsrv(dirsrv)

                emit_err(MSG_HINT_IGNORE_SERVICE_FAILURE)
                raise IpactlError("Aborting ipactl")

    if len(new_svc_list) != 0:
        # we still need to start some services
        for svc in new_svc_list:
            svchandle = services.service(svc, api=api)
            try:
                print("Starting %s Service" % svc)
                svchandle.start(
                    capture_output=get_capture_output(svc, options.debug))
            except Exception:
                emit_err("Failed to start %s Service" % svc)
                # if ignore_service_failures is specified, skip rollback and
                # continue with the next service
                if options.ignore_service_failures:
                    emit_err("Forced start, ignoring %s Service, "
                             "continuing normal operation" % svc)
                    continue

                emit_err("Shutting down")
                stop_services(svc_list)
                stop_dirsrv(dirsrv)

                emit_err(MSG_HINT_IGNORE_SERVICE_FAILURE)
                raise IpactlError("Aborting ipactl")
Пример #46
0
 def __start(self):
     try:
         self.start()
         services.service('winbind', api).start()
     except Exception:
         logger.critical("CIFS services failed to start")
Пример #47
0
def ipa_status(options):
    """Report status of IPA-owned processes

       The LSB defines the possible status values as:

       0 program is running or service is OK
       1 program is dead and /var/run pid file exists
       2 program is dead and /var/lock lock file exists
       3 program is not running
       4 program or service status is unknown
       5-99 reserved for future LSB use
       100-149 reserved for distribution use
       150-199 reserved for application use
       200-254 reserved

       We only really care about 0, 3 and 4.
    """
    socket_activated = (
        'ipa-ods-exporter',
        'ipa-otpd',
    )

    try:
        dirsrv = services.knownservices.dirsrv
        if dirsrv.is_running():
            svc_list = get_config(dirsrv)
        else:
            svc_list = get_config_from_file(rval=1)
    except IpactlError as e:
        if os.path.exists(tasks.get_svc_list_file()):
            raise e
        else:
            svc_list = []
    except Exception as e:
        raise IpactlError(
            "Failed to get list of services to probe status: " + str(e), 4)

    stopped = 0
    dirsrv = services.knownservices.dirsrv
    try:
        if dirsrv.is_running():
            print("Directory Service: RUNNING")
        else:
            print("Directory Service: STOPPED")
            stopped = 1
    except Exception as e:
        raise IpactlError("Failed to get Directory Service status", 4)

    if len(svc_list) == 0:
        raise IpactlError(
            ("Directory Service must be running in order to "
             "obtain status of other services"),
            3,
        )

    for svc in svc_list:
        svchandle = services.service(svc, api=api)
        try:
            if svchandle.is_running():
                print("%s Service: RUNNING" % svc)
            else:
                print("%s Service: STOPPED" % svc)
                if svc not in socket_activated:
                    stopped += 1
        except Exception:
            emit_err("Failed to get %s Service status" % svc)

    if stopped > 0:
        raise IpactlError("%d service(s) are not running" % stopped, 3)