Example #1
0
    def __configure_http(self):
        self.update_httpd_service_ipa_conf()
        self.update_httpd_wsgi_conf()

        # create /etc/httpd/alias, see https://pagure.io/freeipa/issue/7529
        session_dir = os.path.dirname(self.sub_dict['GSSAPI_SESSION_KEY'])
        if not os.path.isdir(session_dir):
            os.makedirs(session_dir)
        # Must be world-readable / executable
        os.chmod(session_dir, 0o755)
        # Restore SELinux context of session_dir /etc/httpd/alias, see
        # https://pagure.io/freeipa/issue/7662
        tasks.restore_context(session_dir)

        target_fname = paths.HTTPD_IPA_CONF
        http_txt = ipautil.template_file(
            os.path.join(paths.USR_SHARE_IPA_DIR,
                         "ipa.conf.template"),
            self.sub_dict)
        self.fstore.backup_file(paths.HTTPD_IPA_CONF)
        http_fd = open(target_fname, "w")
        http_fd.write(http_txt)
        http_fd.close()
        os.chmod(target_fname, 0o644)

        target_fname = paths.HTTPD_IPA_REWRITE_CONF
        http_txt = ipautil.template_file(
            os.path.join(paths.USR_SHARE_IPA_DIR,
                         "ipa-rewrite.conf.template"),
            self.sub_dict)
        self.fstore.backup_file(paths.HTTPD_IPA_REWRITE_CONF)
        http_fd = open(target_fname, "w")
        http_fd.write(http_txt)
        http_fd.close()
        os.chmod(target_fname, 0o644)
Example #2
0
def configure_chrony(ntp_servers, ntp_pool=None,
                     fstore=None, sysstore=None, debug=False):
    """
    This method only configures chrony client with ntp_servers or ntp_pool
    """

    module = "chrony"
    if sysstore:
        sysstore.backup_state(module, "enabled",
                              services.knownservices.chronyd.is_enabled())

    aug = Augeas(flags=Augeas.NO_LOAD | Augeas.NO_MODL_AUTOLOAD,
                 loadpath=paths.USR_SHARE_IPA_DIR)

    try:
        logger.debug("Configuring chrony")
        chrony_conf = os.path.abspath(paths.CHRONY_CONF)
        aug.transform(module, chrony_conf)  # loads chrony lens file
        aug.load()  # loads augeas tree
        # augeas needs to prepend path with '/files'
        path = '/files{path}'.format(path=chrony_conf)

        # remove possible conflicting configuration of servers
        aug.remove('{}/server'.format(path))
        aug.remove('{}/pool'.format(path))
        aug.remove('{}/peer'.format(path))
        if ntp_pool:
            logger.debug("Setting server pool:")
            logger.debug("'%s'", ntp_pool)
            aug.set('{}/pool[last()+1]'.format(path), ntp_pool)
            aug.set('{}/pool[last()]/iburst'.format(path), None)

        if ntp_servers:
            logger.debug("Setting time servers:")
            for server in ntp_servers:
                aug.set('{}/server[last()+1]'.format(path), server)
                aug.set('{}/server[last()]/iburst'.format(path), None)
                logger.debug("'%s'", server)

        # backup oginal conf file
        logger.debug("Backing up '%s'", chrony_conf)
        __backup_config(chrony_conf, fstore)

        logger.debug("Writing configuration to '%s'", chrony_conf)
        aug.save()

        logger.info('Configuration of chrony was changed by installer.')
        configured = True

    except IOError:
        logger.error("Augeas failed to configure file %s", chrony_conf)
        configured = False
    except RuntimeError as e:
        logger.error("Configuration failed with: %s", e)
        configured = False
    finally:
        aug.close()

    tasks.restore_context(chrony_conf)
    return configured
Example #3
0
    def restore_all_files(self):
        """Restore the files in the inbdex to their original
        location and delete the copy.

        Returns #True if the file was restored, #False if there
        was no backup file to restore
        """

        if len(self.files) == 0:
            return False

        for (filename, value) in self.files.items():

            (mode,uid,gid,path) = value.split(',', 3)

            backup_path = os.path.join(self._path, filename)
            if not os.path.exists(backup_path):
                root_logger.debug("  -> Not restoring - '%s' doesn't exist", backup_path)
                continue

            shutil.copy(backup_path, path)  # SELinux needs copy
            os.remove(backup_path)

            os.chown(path, int(uid), int(gid))
            os.chmod(path, int(mode))

            tasks.restore_context(path)

        # force file to be deleted
        self.files = {}
        self.save()

        return True
Example #4
0
    def __update_dse_ldif(self):
        """
        This method updates dse.ldif right after instance creation. This is
        supposed to allow admin modify configuration of the DS which has to be
        done before IPA is fully installed (for example: settings for
        replication on replicas)
        DS must be turned off.
        """
        dse_filename = os.path.join(
            paths.ETC_DIRSRV_SLAPD_INSTANCE_TEMPLATE % self.serverid,
            'dse.ldif'
        )

        with tempfile.NamedTemporaryFile(
                mode='w', delete=False) as new_dse_ldif:
            temp_filename = new_dse_ldif.name
            with open(dse_filename, "r") as input_file:
                parser = installutils.ModifyLDIF(input_file, new_dse_ldif)
                parser.replace_value(
                        'cn=config,cn=ldbm database,cn=plugins,cn=config',
                        'nsslapd-db-locks',
                        [b'50000']
                        )
                if self.config_ldif:
                    # parse modifications from ldif file supplied by the admin
                    with open(self.config_ldif, "r") as config_ldif:
                        parser.modifications_from_ldif(config_ldif)
                parser.parse()
            new_dse_ldif.flush()
        shutil.copy2(temp_filename, dse_filename)
        tasks.restore_context(dse_filename)
        try:
            os.remove(temp_filename)
        except OSError as e:
            logger.debug("Failed to clean temporary file: %s", e)
Example #5
0
    def __configure_instance(self):
        self.__template_file(paths.KRB5KDC_KDC_CONF, chmod=None)
        self.__template_file(paths.KRB5_CONF)
        self.__template_file(paths.HTML_KRB5_INI)
        self.__template_file(paths.KRB_CON)
        self.__template_file(paths.HTML_KRBREALM_CON)

        MIN_KRB5KDC_WITH_WORKERS = "1.9"
        cpus = os.sysconf('SC_NPROCESSORS_ONLN')
        workers = False
        result = ipautil.run([paths.KLIST, '-V'],
                             raiseonerr=False,
                             capture_output=True)
        if result.returncode == 0:
            verstr = result.output.split()[-1]
            ver = tasks.parse_ipa_version(verstr)
            min = tasks.parse_ipa_version(MIN_KRB5KDC_WITH_WORKERS)
            if ver >= min:
                workers = True
        # Write down config file
        # We write realm and also number of workers (for multi-CPU systems)
        replacevars = {'KRB5REALM': self.realm}
        appendvars = {}
        if workers and cpus > 1:
            appendvars = {'KRB5KDC_ARGS': "'-w %s'" % str(cpus)}
        ipautil.backup_config_and_replace_variables(
            self.fstore,
            paths.SYSCONFIG_KRB5KDC_DIR,
            replacevars=replacevars,
            appendvars=appendvars)
        tasks.restore_context(paths.SYSCONFIG_KRB5KDC_DIR)
Example #6
0
    def __configure_instance(self):
        self.__template_file(paths.KRB5KDC_KDC_CONF, chmod=None)
        self.__template_file(paths.KRB5_CONF)
        self.__template_file(paths.HTML_KRB5_INI)
        self.__template_file(paths.KRB_CON)
        self.__template_file(paths.HTML_KRBREALM_CON)

        MIN_KRB5KDC_WITH_WORKERS = "1.9"
        cpus = os.sysconf('SC_NPROCESSORS_ONLN')
        workers = False
        result = ipautil.run(['klist', '-V'],
                             raiseonerr=False, capture_output=True)
        if result.returncode == 0:
            verstr = result.output.split()[-1]
            ver = tasks.parse_ipa_version(verstr)
            min = tasks.parse_ipa_version(MIN_KRB5KDC_WITH_WORKERS)
            if ver >= min:
                workers = True
        # Write down config file
        # We write realm and also number of workers (for multi-CPU systems)
        replacevars = {'KRB5REALM':self.realm}
        appendvars = {}
        if workers and cpus > 1:
            appendvars = {'KRB5KDC_ARGS': "'-w %s'" % str(cpus)}
        ipautil.backup_config_and_replace_variables(self.fstore, paths.SYSCONFIG_KRB5KDC_DIR,
                                                    replacevars=replacevars,
                                                    appendvars=appendvars)
        tasks.restore_context(paths.SYSCONFIG_KRB5KDC_DIR)
Example #7
0
    def tune_nofile_platform(self, num=8192, fstore=None):
        """
        Increase the number of files descriptors available to directory server
        from the default 1024 to 8192. This will allow to support a greater
        number of clients out of the box.

        This is a part of the implementation that is systemd-specific.

        Returns False if the setting of the nofile limit needs to be skipped.
        """

        if os.path.exists(paths.SYSCONFIG_DIRSRV_SYSTEMD):
            # We need to enable LimitNOFILE=8192 in the [email protected]
            # Since 389-ds-base-1.2.10-0.8.a7 the configuration of the
            # service parameters is performed via
            # /etc/sysconfig/dirsrv.systemd file which is imported by systemd
            # into [email protected] unit

            replacevars = {'LimitNOFILE': str(num)}
            ipautil.inifile_replace_variables(paths.SYSCONFIG_DIRSRV_SYSTEMD,
                                              'service',
                                              replacevars=replacevars)
            tasks.restore_context(paths.SYSCONFIG_DIRSRV_SYSTEMD)
            ipautil.run(["/bin/systemctl", "--system", "daemon-reload"],
                        raiseonerr=False)

        return True
Example #8
0
    def __create_dogtag_log_dirs(self):
        """
        If we are doing a full restore and the dogtag log directories do
        not exist then tomcat will fail to start.

        The directory is different depending on whether we have a d9-based
        or a d10-based installation.
        """
        dirs = []
        # dogtag 10
        if (os.path.exists(paths.VAR_LIB_PKI_TOMCAT_DIR) and
                not os.path.exists(paths.TOMCAT_TOPLEVEL_DIR)):
            dirs += [paths.TOMCAT_TOPLEVEL_DIR,
                     paths.TOMCAT_CA_DIR,
                     paths.TOMCAT_CA_ARCHIVE_DIR,
                     paths.TOMCAT_SIGNEDAUDIT_DIR]

        try:
            pent = pwd.getpwnam(constants.PKI_USER)
        except KeyError:
            logger.debug("No %s user exists, skipping CA directory creation",
                         constants.PKI_USER)
            return
        logger.debug('Creating log directories for dogtag')
        for dir in dirs:
            try:
                logger.debug('Creating %s', dir)
                os.mkdir(dir)
                os.chmod(dir, 0o770)
                os.chown(dir, pent.pw_uid, pent.pw_gid)
                tasks.restore_context(dir)
            except Exception as e:
                # This isn't so fatal as to side-track the restore
                logger.error('Problem with %s: %s', dir, e)
Example #9
0
def configure_chrony(ntp_servers, ntp_pool=None,
                     fstore=None, sysstore=None, debug=False):
    """
    This method only configures chrony client with ntp_servers or ntp_pool
    """

    module = "chrony"
    if sysstore:
        sysstore.backup_state(module, "enabled",
                              services.knownservices.chronyd.is_enabled())

    aug = Augeas(flags=Augeas.NO_LOAD | Augeas.NO_MODL_AUTOLOAD,
                 loadpath=paths.USR_SHARE_IPA_DIR)

    try:
        logger.debug("Configuring chrony")
        chrony_conf = os.path.abspath(paths.CHRONY_CONF)
        aug.transform(module, chrony_conf)  # loads chrony lens file
        aug.load()  # loads augeas tree
        # augeas needs to prepend path with '/files'
        path = '/files{path}'.format(path=chrony_conf)

        # remove possible conflicting configuration of servers
        aug.remove('{}/server'.format(path))
        aug.remove('{}/pool'.format(path))
        aug.remove('{}/peer'.format(path))
        if ntp_pool:
            logger.debug("Setting server pool:")
            logger.debug("'%s'", ntp_pool)
            aug.set('{}/pool[last()+1]'.format(path), ntp_pool)
            aug.set('{}/pool[last()]/iburst'.format(path), None)

        if ntp_servers:
            logger.debug("Setting time servers:")
            for server in ntp_servers:
                aug.set('{}/server[last()+1]'.format(path), server)
                aug.set('{}/server[last()]/iburst'.format(path), None)
                logger.debug("'%s'", server)

        # backup oginal conf file
        logger.debug("Backing up '%s'", chrony_conf)
        __backup_config(chrony_conf, fstore)

        logger.debug("Writing configuration to '%s'", chrony_conf)
        aug.save()

        logger.info('Configuration of chrony was changed by installer.')
        configured = True

    except IOError:
        logger.error("Augeas failed to configure file %s", chrony_conf)
        configured = False
    except RuntimeError as e:
        logger.error("Configuration failed with: %s", e)
        configured = False
    finally:
        aug.close()

    tasks.restore_context(chrony_conf)
    return configured
Example #10
0
    def __create_dogtag_log_dirs(self):
        """
        If we are doing a full restore and the dogtag log directories do
        not exist then tomcat will fail to start.

        The directory is different depending on whether we have a d9-based
        or a d10-based installation.
        """
        dirs = []
        # dogtag 10
        if (os.path.exists(paths.VAR_LIB_PKI_TOMCAT_DIR) and
                not os.path.exists(paths.TOMCAT_TOPLEVEL_DIR)):
            dirs += [paths.TOMCAT_TOPLEVEL_DIR,
                     paths.TOMCAT_CA_DIR,
                     paths.TOMCAT_CA_ARCHIVE_DIR,
                     paths.TOMCAT_SIGNEDAUDIT_DIR]

        try:
            pent = pwd.getpwnam(constants.PKI_USER)
        except KeyError:
            self.log.debug("No %s user exists, skipping CA directory creation",
                           constants.PKI_USER)
            return
        self.log.debug('Creating log directories for dogtag')
        for dir in dirs:
            try:
                self.log.debug('Creating %s' % dir)
                os.mkdir(dir)
                os.chmod(dir, 0o770)
                os.chown(dir, pent.pw_uid, pent.pw_gid)
                tasks.restore_context(dir)
            except Exception as e:
                # This isn't so fatal as to side-track the restore
                self.log.error('Problem with %s: %s' % (dir, e))
Example #11
0
    def tune_nofile_platform(self, num=8192, fstore=None):
        """
        Increase the number of files descriptors available to directory server
        from the default 1024 to 8192. This will allow to support a greater
        number of clients out of the box.

        This is a part of the implementation that is systemd-specific.

        Returns False if the setting of the nofile limit needs to be skipped.
        """

        if os.path.exists(paths.SYSCONFIG_DIRSRV_SYSTEMD):
            # We need to enable LimitNOFILE=8192 in the [email protected]
            # Since 389-ds-base-1.2.10-0.8.a7 the configuration of the
            # service parameters is performed via
            # /etc/sysconfig/dirsrv.systemd file which is imported by systemd
            # into [email protected] unit

            replacevars = {'LimitNOFILE': str(num)}
            ipautil.inifile_replace_variables(paths.SYSCONFIG_DIRSRV_SYSTEMD,
                                              'service',
                                              replacevars=replacevars)
            tasks.restore_context(paths.SYSCONFIG_DIRSRV_SYSTEMD)
            ipautil.run(["/bin/systemctl", "--system", "daemon-reload"],
                        raiseonerr=False)

        return True
Example #12
0
    def restore_all_files(self):
        """Restore the files in the inbdex to their original
        location and delete the copy.

        Returns #True if the file was restored, #False if there
        was no backup file to restore
        """

        if len(self.files) == 0:
            return False

        for (filename, value) in self.files.items():

            (mode,uid,gid,path) = value.split(',', 3)

            backup_path = os.path.join(self._path, filename)
            if not os.path.exists(backup_path):
                logger.debug("  -> Not restoring - '%s' doesn't exist",
                             backup_path)
                continue

            shutil.copy(backup_path, path)  # SELinux needs copy
            os.remove(backup_path)

            os.chown(path, int(uid), int(gid))
            os.chmod(path, int(mode))

            tasks.restore_context(path)

        # force file to be deleted
        self.files = {}
        self.save()

        return True
Example #13
0
    def __configure_http(self):
        self.update_httpd_service_ipa_conf()
        self.update_httpd_wsgi_conf()

        # create /etc/httpd/alias, see https://pagure.io/freeipa/issue/7529
        session_dir = os.path.dirname(self.sub_dict['GSSAPI_SESSION_KEY'])
        if not os.path.isdir(session_dir):
            os.makedirs(session_dir)
        # Must be world-readable / executable
        os.chmod(session_dir, 0o755)
        # Restore SELinux context of session_dir /etc/httpd/alias, see
        # https://pagure.io/freeipa/issue/7662
        tasks.restore_context(session_dir)

        target_fname = paths.HTTPD_IPA_CONF
        http_txt = ipautil.template_file(
            os.path.join(paths.USR_SHARE_IPA_DIR, "ipa.conf.template"),
            self.sub_dict)
        self.fstore.backup_file(paths.HTTPD_IPA_CONF)
        http_fd = open(target_fname, "w")
        http_fd.write(http_txt)
        http_fd.close()
        os.chmod(target_fname, 0o644)

        target_fname = paths.HTTPD_IPA_REWRITE_CONF
        http_txt = ipautil.template_file(
            os.path.join(paths.USR_SHARE_IPA_DIR, "ipa-rewrite.conf.template"),
            self.sub_dict)
        self.fstore.backup_file(paths.HTTPD_IPA_REWRITE_CONF)
        http_fd = open(target_fname, "w")
        http_fd.write(http_txt)
        http_fd.close()
        os.chmod(target_fname, 0o644)
Example #14
0
def configure_autofs(fstore, statestore, autodiscover, server, options):
    """
    fstore: the FileStore to back up files in
    options.server: the IPA server to use
    options.location: the Automount location to use
    """
    if not autodiscover:
        ldap_uri = "ldap://%s" % server
    else:
        ldap_uri = "ldap:///%s" % api.env.basedn

    search_base = str(
        DN(
            ('cn', options.location),
            api.env.container_automount,
            api.env.basedn,
        )
    )
    replacevars = {
        'MAP_OBJECT_CLASS': 'automountMap',
        'ENTRY_OBJECT_CLASS': 'automount',
        'MAP_ATTRIBUTE': 'automountMapName',
        'ENTRY_ATTRIBUTE': 'automountKey',
        'VALUE_ATTRIBUTE': 'automountInformation',
        'SEARCH_BASE': search_base,
        'LDAP_URI': ldap_uri,
    }

    ipautil.backup_config_and_replace_variables(
        fstore, paths.SYSCONFIG_AUTOFS, replacevars=replacevars
    )
    tasks.restore_context(paths.SYSCONFIG_AUTOFS)
    statestore.backup_state('autofs', 'sssd', False)

    print("Configured %s" % paths.SYSCONFIG_AUTOFS)
Example #15
0
    def __update_dse_ldif(self):
        """
        This method updates dse.ldif right after instance creation. This is
        supposed to allow admin modify configuration of the DS which has to be
        done before IPA is fully installed (for example: settings for
        replication on replicas)
        DS must be turned off.
        """
        dse_filename = os.path.join(
            paths.ETC_DIRSRV_SLAPD_INSTANCE_TEMPLATE % self.serverid,
            'dse.ldif')

        with tempfile.NamedTemporaryFile(mode='w',
                                         delete=False) as new_dse_ldif:
            temp_filename = new_dse_ldif.name
            with open(dse_filename, "r") as input_file:
                parser = installutils.ModifyLDIF(input_file, new_dse_ldif)
                parser.replace_value(
                    'cn=config,cn=ldbm database,cn=plugins,cn=config',
                    'nsslapd-db-locks', [b'50000'])
                if self.config_ldif:
                    # parse modifications from ldif file supplied by the admin
                    with open(self.config_ldif, "r") as config_ldif:
                        parser.modifications_from_ldif(config_ldif)
                parser.parse()
            new_dse_ldif.flush()
        shutil.copy2(temp_filename, dse_filename)
        tasks.restore_context(dse_filename)
        try:
            os.remove(temp_filename)
        except OSError as e:
            logger.debug("Failed to clean temporary file: %s", e)
Example #16
0
    def fix_cert_db_perms(self):
        pent = pwd.getpwnam(self.service_user)

        for filename in NSS_FILES:
            nss_path = os.path.join(certs.NSS_DIR, filename)
            os.chmod(nss_path, 0o640)
            os.chown(nss_path, 0, pent.pw_gid)
            tasks.restore_context(nss_path)
Example #17
0
    def fix_cert_db_perms(self):
        pent = pwd.getpwnam(self.service_user)

        for filename in NSS_FILES:
            nss_path = os.path.join(certs.NSS_DIR, filename)
            os.chmod(nss_path, 0o640)
            os.chown(nss_path, 0, pent.pw_gid)
            tasks.restore_context(nss_path)
Example #18
0
    def restore_file(self, path, new_path=None):
        """Restore the copy of a file at @path to its original
        location and delete the copy.

        Takes optional parameter @new_path which specifies the
        location where the file is to be restored.

        Returns #True if the file was restored, #False if there
        was no backup file to restore
        """

        if new_path is None:
            logger.debug("Restoring system configuration file '%s'",
                         path)
        else:
            logger.debug("Restoring system configuration file '%s' to '%s'",
                         path, new_path)

        if not os.path.isabs(path):
            raise ValueError("Absolute path required")
        if new_path is not None and not os.path.isabs(new_path):
            raise ValueError("Absolute new path required")

        mode = None
        uid = None
        gid = None
        filename = None

        for (key, value) in self.files.items():
            (mode,uid,gid,filepath) = value.split(',', 3)
            if (filepath == path):
                filename = key
                break

        if not filename:
            raise ValueError("No such file name in the index")

        backup_path = os.path.join(self._path, filename)
        if not os.path.exists(backup_path):
            logger.debug("  -> Not restoring - '%s' doesn't exist",
                         backup_path)
            return False

        if new_path is not None:
            path = new_path

        shutil.copy(backup_path, path)  # SELinux needs copy
        os.remove(backup_path)

        os.chown(path, int(uid), int(gid))
        os.chmod(path, int(mode))

        tasks.restore_context(path)

        del self.files[filename]
        self.save()

        return True
Example #19
0
    def restore_file(self, path, new_path = None):
        """Restore the copy of a file at @path to its original
        location and delete the copy.

        Takes optional parameter @new_path which specifies the
        location where the file is to be restored.

        Returns #True if the file was restored, #False if there
        was no backup file to restore
        """

        if new_path is None:
            logger.debug("Restoring system configuration file '%s'",
                         path)
        else:
            logger.debug("Restoring system configuration file '%s' to '%s'",
                         path, new_path)

        if not os.path.isabs(path):
            raise ValueError("Absolute path required")
        if new_path is not None and not os.path.isabs(new_path):
            raise ValueError("Absolute new path required")

        mode = None
        uid = None
        gid = None
        filename = None

        for (key, value) in self.files.items():
            (mode,uid,gid,filepath) = value.split(',', 3)
            if (filepath == path):
                filename = key
                break

        if not filename:
            raise ValueError("No such file name in the index")

        backup_path = os.path.join(self._path, filename)
        if not os.path.exists(backup_path):
            logger.debug("  -> Not restoring - '%s' doesn't exist",
                         backup_path)
            return False

        if new_path is not None:
            path = new_path

        shutil.copy(backup_path, path)  # SELinux needs copy
        os.remove(backup_path)

        os.chown(path, int(uid), int(gid))
        os.chmod(path, int(mode))

        tasks.restore_context(path)

        del self.files[filename]
        self.save()

        return True
Example #20
0
    def create_db(self, user=None, group=None, mode=None, backup=False):
        """Create cert DB

        :param user: User owner the secdir
        :param group: Group owner of the secdir
        :param mode: Mode of the secdir
        :param backup: Backup the sedir files
        """
        dirmode = 0o750
        filemode = 0o640
        pwdfilemode = 0o640
        if mode is not None:
            dirmode = mode
            filemode = mode & 0o666
            pwdfilemode = mode & 0o660

        uid = -1
        gid = -1
        if user is not None:
            uid = pwd.getpwnam(user).pw_uid
        if group is not None:
            gid = grp.getgrnam(group).gr_gid

        if backup:
            for filename in NSS_FILES:
                path = os.path.join(self.secdir, filename)
                ipautil.backup_file(path)

        if not os.path.exists(self.secdir):
            os.makedirs(self.secdir, dirmode)

        if not os.path.exists(self.pwd_file):
            # Create the password file for this db
            with io.open(os.open(self.pwd_file, os.O_CREAT | os.O_WRONLY,
                                 pwdfilemode),
                         'w',
                         closefd=True) as f:
                f.write(ipautil.ipa_generate_password())
                f.flush()

        self.run_certutil(["-N", "-f", self.pwd_file])

        # Finally fix up perms
        os.chown(self.secdir, uid, gid)
        os.chmod(self.secdir, dirmode)
        tasks.restore_context(self.secdir)
        for filename in NSS_FILES:
            path = os.path.join(self.secdir, filename)
            if os.path.exists(path):
                if uid != -1 or gid != -1:
                    os.chown(path, uid, gid)
                if path == self.pwd_file:
                    new_mode = pwdfilemode
                else:
                    new_mode = filemode
                os.chmod(path, new_mode)
                tasks.restore_context(path)
Example #21
0
    def __setup_ssl(self):
        fqdn = self.fqdn

        ca_db = certs.CertDB(self.realm, host_name=fqdn, subject_base=self.subject_base)

        db = certs.CertDB(self.realm, subject_base=self.subject_base)
        if self.pkcs12_info:
            if self.ca_is_configured:
                trust_flags = 'CT,C,C'
            else:
                trust_flags = None
            db.create_from_pkcs12(self.pkcs12_info[0], self.pkcs12_info[1],
                                  passwd=None, ca_file=self.ca_file,
                                  trust_flags=trust_flags)
            server_certs = db.find_server_certs()
            if len(server_certs) == 0:
                raise RuntimeError("Could not find a suitable server cert in import in %s" % self.pkcs12_info[0])

            db.create_password_conf()

            # We only handle one server cert
            nickname = server_certs[0][0]
            self.dercert = db.get_cert_from_db(nickname, pem=False)

            if self.ca_is_configured:
                db.track_server_cert(nickname, self.principal, db.passwd_fname, 'restart_httpd')

            self.__set_mod_nss_nickname(nickname)
            self.add_cert_to_service()

        elif not self.promote:
            db.create_password_conf()
            self.dercert = db.create_server_cert(self.cert_nickname, self.fqdn,
                                                 ca_db)
            db.track_server_cert(self.cert_nickname, self.principal,
                                 db.passwd_fname, 'restart_httpd')
            db.create_signing_cert("Signing-Cert", "Object Signing Cert", ca_db)
            self.add_cert_to_service()

        # Fix the database permissions
        os.chmod(certs.NSS_DIR + "/cert8.db", 0o660)
        os.chmod(certs.NSS_DIR + "/key3.db", 0o660)
        os.chmod(certs.NSS_DIR + "/secmod.db", 0o660)
        os.chmod(certs.NSS_DIR + "/pwdfile.txt", 0o660)

        pent = pwd.getpwnam(HTTPD_USER)
        os.chown(certs.NSS_DIR + "/cert8.db", 0, pent.pw_gid )
        os.chown(certs.NSS_DIR + "/key3.db", 0, pent.pw_gid )
        os.chown(certs.NSS_DIR + "/secmod.db", 0, pent.pw_gid )
        os.chown(certs.NSS_DIR + "/pwdfile.txt", 0, pent.pw_gid )

        # Fix SELinux permissions on the database
        tasks.restore_context(certs.NSS_DIR + "/cert8.db")
        tasks.restore_context(certs.NSS_DIR + "/key3.db")
Example #22
0
    def __setup_ssl(self):
        fqdn = self.fqdn

        ca_db = certs.CertDB(self.realm, host_name=fqdn, subject_base=self.subject_base)

        db = certs.CertDB(self.realm, subject_base=self.subject_base)
        if self.pkcs12_info:
            if self.ca_is_configured:
                trust_flags = 'CT,C,C'
            else:
                trust_flags = None
            db.create_from_pkcs12(self.pkcs12_info[0], self.pkcs12_info[1],
                                  passwd=None, ca_file=self.ca_file,
                                  trust_flags=trust_flags)
            server_certs = db.find_server_certs()
            if len(server_certs) == 0:
                raise RuntimeError("Could not find a suitable server cert in import in %s" % self.pkcs12_info[0])

            db.create_password_conf()

            # We only handle one server cert
            nickname = server_certs[0][0]
            self.dercert = db.get_cert_from_db(nickname, pem=False)

            if self.ca_is_configured:
                db.track_server_cert(nickname, self.principal, db.passwd_fname, 'restart_httpd')

            self.__set_mod_nss_nickname(nickname)
            self.add_cert_to_service()

        elif not self.promote:
            db.create_password_conf()
            self.dercert = db.create_server_cert(self.cert_nickname, self.fqdn,
                                                 ca_db)
            db.track_server_cert(self.cert_nickname, self.principal,
                                 db.passwd_fname, 'restart_httpd')
            db.create_signing_cert("Signing-Cert", "Object Signing Cert", ca_db)
            self.add_cert_to_service()

        # Fix the database permissions
        os.chmod(certs.NSS_DIR + "/cert8.db", 0o660)
        os.chmod(certs.NSS_DIR + "/key3.db", 0o660)
        os.chmod(certs.NSS_DIR + "/secmod.db", 0o660)
        os.chmod(certs.NSS_DIR + "/pwdfile.txt", 0o660)

        pent = pwd.getpwnam(HTTPD_USER)
        os.chown(certs.NSS_DIR + "/cert8.db", 0, pent.pw_gid )
        os.chown(certs.NSS_DIR + "/key3.db", 0, pent.pw_gid )
        os.chown(certs.NSS_DIR + "/secmod.db", 0, pent.pw_gid )
        os.chown(certs.NSS_DIR + "/pwdfile.txt", 0, pent.pw_gid )

        # Fix SELinux permissions on the database
        tasks.restore_context(certs.NSS_DIR + "/cert8.db")
        tasks.restore_context(certs.NSS_DIR + "/key3.db")
Example #23
0
    def configure_dirsrv_ccache(self):
        pent = pwd.getpwnam(platformconstants.DS_USER)
        ccache = paths.TMP_KRB5CC % pent.pw_uid
        filepath = paths.SYSCONFIG_DIRSRV
        if not os.path.exists(filepath):
            # file doesn't exist; create it with correct ownership & mode
            open(filepath, "a").close()
            os.chmod(filepath, stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
            os.chown(filepath, 0, 0)

        replacevars = {"KRB5CCNAME": ccache}
        ipautil.backup_config_and_replace_variables(self.fstore, filepath, replacevars=replacevars)
        tasks.restore_context(filepath)
Example #24
0
def configure_nfs(fstore, statestore, options):
    """
    Configure secure NFS
    """
    # Newer Fedora releases ship /etc/nfs.conf instead of /etc/sysconfig/nfs
    # and do not require changes there. On these, SECURE_NFS_VAR == None
    if constants.SECURE_NFS_VAR:
        replacevars = {constants.SECURE_NFS_VAR: 'yes'}
        ipautil.backup_config_and_replace_variables(
            fstore, paths.SYSCONFIG_NFS, replacevars=replacevars
        )
        tasks.restore_context(paths.SYSCONFIG_NFS)
        print("Configured %s" % paths.SYSCONFIG_NFS)

    # Prepare the changes
    # We need to use IPAChangeConf as simple regexp substitution
    # does not cut it here
    conf = ipachangeconf.IPAChangeConf("IPA automount installer")
    conf.case_insensitive_sections = False
    conf.setOptionAssignment(" = ")
    conf.setSectionNameDelimiters(("[", "]"))

    if options.idmapdomain is None:
        # Set NFSv4 domain to the IPA domain
        changes = [conf.setOption('Domain', api.env.domain)]
    elif options.idmapdomain == 'DNS':
        # Rely on idmapd auto-detection (DNS)
        changes = [conf.rmOption('Domain')]
    else:
        # Set NFSv4 domain to what was provided
        changes = [conf.setOption('Domain', options.idmapdomain)]

    if changes is not None:
        section_with_changes = [conf.setSection('General', changes)]
        # Backup the file and apply the changes
        fstore.backup_file(paths.IDMAPD_CONF)
        conf.changeConf(paths.IDMAPD_CONF, section_with_changes)
        tasks.restore_context(paths.IDMAPD_CONF)
        print("Configured %s" % paths.IDMAPD_CONF)

    rpcgssd = services.knownservices.rpcgssd
    try:
        rpcgssd.restart()
    except Exception as e:
        logger.error("Failed to restart rpc-gssd (%s)", str(e))
    nfsutils = services.knownservices['nfs-utils']
    try:
        nfsutils.restart()
    except Exception as e:
        logger.error("Failed to restart nfs client services (%s)", str(e))
Example #25
0
    def convert_db(self, rename_old=True):
        """Convert DBM database format to SQL database format

        **WARNING** **WARNING** **WARNING** **WARNING** **WARNING**

        The caller must ensure that no other process or service is
        accessing the NSSDB during migration. The DBM format does not support
        multiple processes. If more than one process opens a DBM NSSDB for
        writing, the database will become **irreparably corrupted**.

        **WARNING** **WARNING** **WARNING** **WARNING** **WARNING**
        """
        if (self.dbtype == 'sql' or
                os.path.isfile(os.path.join(self.secdir, "cert9.db"))):
            raise ValueError(
                'NSS DB {} has been migrated already.'.format(self.secdir)
            )

        # use certutil to migrate db to new format
        # see https://bugzilla.mozilla.org/show_bug.cgi?id=1415912
        # https://fedoraproject.org/wiki/Changes/NSSDefaultFileFormatSql
        args = [
            paths.CERTUTIL,
            '-d', 'sql:{}'.format(self.secdir), '-N',
            '-f', self.pwd_file, '-@', self.pwd_file
        ]
        ipautil.run(args, stdin=None, cwd=self.secdir)

        # retain file ownership and permission, backup old files
        migration = (
            ('cert8.db', 'cert9.db'),
            ('key3.db', 'key4.db'),
            ('secmod.db', 'pkcs11.txt'),
        )
        for oldname, newname in migration:
            oldname = os.path.join(self.secdir, oldname)
            newname = os.path.join(self.secdir, newname)
            oldstat = os.stat(oldname)
            os.chmod(newname, stat.S_IMODE(oldstat.st_mode))
            os.chown(newname, oldstat.st_uid, oldstat.st_gid)
            tasks.restore_context(newname, force=True)

        self._set_filenames('sql')
        self.list_certs()  # self-test

        if rename_old:
            for oldname, _ in migration:  # pylint: disable=unused-variable
                oldname = os.path.join(self.secdir, oldname)
                os.rename(oldname, oldname + '.migrated')
Example #26
0
    def convert_db(self, rename_old=True):
        """Convert DBM database format to SQL database format

        **WARNING** **WARNING** **WARNING** **WARNING** **WARNING**

        The caller must ensure that no other process or service is
        accessing the NSSDB during migration. The DBM format does not support
        multiple processes. If more than one process opens a DBM NSSDB for
        writing, the database will become **irreparably corrupted**.

        **WARNING** **WARNING** **WARNING** **WARNING** **WARNING**
        """
        if (self.dbtype == 'sql' or
                os.path.isfile(os.path.join(self.secdir, "cert9.db"))):
            raise ValueError(
                'NSS DB {} has been migrated already.'.format(self.secdir)
            )

        # use certutil to migrate db to new format
        # see https://bugzilla.mozilla.org/show_bug.cgi?id=1415912
        # https://fedoraproject.org/wiki/Changes/NSSDefaultFileFormatSql
        args = [
            paths.CERTUTIL,
            '-d', 'sql:{}'.format(self.secdir), '-N',
            '-f', self.pwd_file, '-@', self.pwd_file
        ]
        ipautil.run(args, stdin=None, cwd=self.secdir)

        # retain file ownership and permission, backup old files
        migration = (
            ('cert8.db', 'cert9.db'),
            ('key3.db', 'key4.db'),
            ('secmod.db', 'pkcs11.txt'),
        )
        for oldname, newname in migration:
            oldname = os.path.join(self.secdir, oldname)
            newname = os.path.join(self.secdir, newname)
            oldstat = os.stat(oldname)
            os.chmod(newname, stat.S_IMODE(oldstat.st_mode))
            os.chown(newname, oldstat.st_uid, oldstat.st_gid)
            tasks.restore_context(newname, force=True)

        self._set_filenames('sql')
        self.list_certs()  # self-test

        if rename_old:
            for oldname, _ in migration:  # pylint: disable=unused-variable
                oldname = os.path.join(self.secdir, oldname)
                os.rename(oldname, oldname + '.migrated')
Example #27
0
    def configure_dirsrv_ccache(self):
        pent = pwd.getpwnam(platformconstants.DS_USER)
        ccache = paths.TMP_KRB5CC % pent.pw_uid
        filepath = paths.SYSCONFIG_DIRSRV
        if not os.path.exists(filepath):
            # file doesn't exist; create it with correct ownership & mode
            open(filepath, 'a').close()
            os.chmod(filepath,
                stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
            os.chown(filepath, 0, 0)

        replacevars = {'KRB5CCNAME': ccache}
        ipautil.backup_config_and_replace_variables(
            self.fstore, filepath, replacevars=replacevars)
        tasks.restore_context(filepath)
Example #28
0
def configure_smb_conf(fstore, statestore, options, domains):
    sub_dict = {
        "samba_keytab": paths.SAMBA_KEYTAB,
        "realm": api.env.realm,
        "machine_name": options.netbiosname,
    }

    # First domain in the list is ours, pull our domain name from there
    sub_dict["netbios_name"] = domains[0]["netbios_name"]

    # Construct elements of smb.conf by pre-rendering idmap configuration
    template = [smb_conf_template]
    for dom in domains:
        template.extend([ipautil.template_str(idmap_conf_domain_snippet, dom)])

    # Add default homes share so that users can log into Samba
    if not options.no_homes:
        template.extend([homes_conf_snippet])

    fstore.backup_file(paths.SMB_CONF)
    with open(paths.SMB_CONF, "w") as f:
        f.write(ipautil.template_str("\n".join(template), sub_dict))
    tasks.restore_context(paths.SMB_CONF)
Example #29
0
def config_ntp(ntp_servers, fstore = None, sysstore = None):
    path_step_tickers = paths.NTP_STEP_TICKERS
    path_ntp_conf = paths.NTP_CONF
    path_ntp_sysconfig = paths.SYSCONFIG_NTPD
    sub_dict = {}
    sub_dict["SERVERS_BLOCK"] = "\n".join("server %s" % s for s in ntp_servers)
    sub_dict["TICKER_SERVERS_BLOCK"] = "\n".join(ntp_servers)

    nc = ipautil.template_str(ntp_conf, sub_dict)
    config_step_tickers = False


    if os.path.exists(path_step_tickers):
        config_step_tickers = True
        ns = ipautil.template_str(ntp_step_tickers, sub_dict)
        __backup_config(path_step_tickers, fstore)
        __write_config(path_step_tickers, ns)
        tasks.restore_context(path_step_tickers)

    if sysstore:
        module = 'ntp'
        sysstore.backup_state(module, "enabled", services.knownservices.ntpd.is_enabled())
        if config_step_tickers:
            sysstore.backup_state(module, "step-tickers", True)

    __backup_config(path_ntp_conf, fstore)
    __write_config(path_ntp_conf, nc)
    tasks.restore_context(path_ntp_conf)

    __backup_config(path_ntp_sysconfig, fstore)
    __write_config(path_ntp_sysconfig, ntp_sysconfig)
    tasks.restore_context(path_ntp_sysconfig)

    # Set the ntpd to start on boot
    services.knownservices.ntpd.enable()

    # Restart ntpd
    services.knownservices.ntpd.restart()
Example #30
0
def config_ntp(ntp_servers, fstore=None, sysstore=None):
    path_step_tickers = paths.NTP_STEP_TICKERS
    path_ntp_conf = paths.NTP_CONF
    path_ntp_sysconfig = paths.SYSCONFIG_NTPD
    sub_dict = {}
    sub_dict["SERVERS_BLOCK"] = "\n".join("server %s" % s for s in ntp_servers)
    sub_dict["TICKER_SERVERS_BLOCK"] = "\n".join(ntp_servers)

    nc = ipautil.template_str(ntp_conf, sub_dict)
    config_step_tickers = False

    if os.path.exists(path_step_tickers):
        config_step_tickers = True
        ns = ipautil.template_str(ntp_step_tickers, sub_dict)
        __backup_config(path_step_tickers, fstore)
        __write_config(path_step_tickers, ns)
        tasks.restore_context(path_step_tickers)

    if sysstore:
        module = 'ntp'
        sysstore.backup_state(module, "enabled",
                              services.knownservices.ntpd.is_enabled())
        if config_step_tickers:
            sysstore.backup_state(module, "step-tickers", True)

    __backup_config(path_ntp_conf, fstore)
    __write_config(path_ntp_conf, nc)
    tasks.restore_context(path_ntp_conf)

    __backup_config(path_ntp_sysconfig, fstore)
    __write_config(path_ntp_sysconfig, ntp_sysconfig)
    tasks.restore_context(path_ntp_sysconfig)

    # Set the ntpd to start on boot
    services.knownservices.ntpd.enable()

    # Restart ntpd
    services.knownservices.ntpd.restart()
Example #31
0
def install(installer):
    options = installer
    fstore = installer._fstore
    sstore = installer._sstore
    dirsrv_pkcs12_file = installer._dirsrv_pkcs12_file
    http_pkcs12_file = installer._http_pkcs12_file
    pkinit_pkcs12_file = installer._pkinit_pkcs12_file
    dirsrv_pkcs12_info = installer._dirsrv_pkcs12_info
    http_pkcs12_info = installer._http_pkcs12_info
    pkinit_pkcs12_info = installer._pkinit_pkcs12_info
    external_cert_file = installer._external_cert_file
    external_ca_file = installer._external_ca_file
    http_ca_cert = installer._ca_cert

    realm_name = options.realm_name
    domain_name = options.domain_name
    dm_password = options.dm_password
    master_password = options.master_password
    admin_password = options.admin_password
    host_name = options.host_name
    ip_addresses = options.ip_addresses
    setup_ca = options.setup_ca
    setup_kra = options.setup_kra

    # Installation has started. No IPA sysrestore items are restored in case of
    # failure to enable root cause investigation
    installer._installation_cleanup = False

    if installer.interactive:
        print("")
        print("The following operations may take some minutes to complete.")
        print("Please wait until the prompt is returned.")
        print("")

    # configure /etc/sysconfig/network to contain the custom hostname
    tasks.backup_and_replace_hostname(fstore, sstore, host_name)

    # set hostname (we need both transient and static)
    tasks.set_hostname(host_name)

    if installer._update_hosts_file:
        update_hosts_file(ip_addresses, host_name, fstore)

    # Create DS user/group if it doesn't exist yet
    dsinstance.create_ds_user()

    # Create a directory server instance
    if not options.external_cert_files:
        # Configure ntpd
        if not options.no_ntp:
            ipaclient.ntpconf.force_ntpd(sstore)
            ntp = ntpinstance.NTPInstance(fstore)
            if not ntp.is_configured():
                ntp.create_instance()

        if options.dirsrv_cert_files:
            ds = dsinstance.DsInstance(fstore=fstore,
                                       domainlevel=options.domainlevel,
                                       config_ldif=options.dirsrv_config_file)
            installer._ds = ds
            ds.create_instance(realm_name, host_name, domain_name,
                               dm_password, dirsrv_pkcs12_info,
                               idstart=options.idstart, idmax=options.idmax,
                               subject_base=options.subject,
                               hbac_allow=not options.no_hbac_allow)
        else:
            ds = dsinstance.DsInstance(fstore=fstore,
                                       domainlevel=options.domainlevel,
                                       config_ldif=options.dirsrv_config_file)
            installer._ds = ds
            ds.create_instance(realm_name, host_name, domain_name,
                               dm_password,
                               idstart=options.idstart, idmax=options.idmax,
                               subject_base=options.subject,
                               hbac_allow=not options.no_hbac_allow)

        ntpinstance.ntp_ldap_enable(host_name, ds.suffix, realm_name)

    else:
        ds = dsinstance.DsInstance(fstore=fstore,
                                   domainlevel=options.domainlevel)
        installer._ds = ds
        ds.init_info(
            realm_name, host_name, domain_name, dm_password,
            options.subject, 1101, 1100, None)

    if setup_ca:
        if not options.external_cert_files and options.external_ca:
            # stage 1 of external CA installation
            options.realm_name = realm_name
            options.domain_name = domain_name
            options.master_password = master_password
            options.dm_password = dm_password
            options.admin_password = admin_password
            options.host_name = host_name
            options.reverse_zones = dns.reverse_zones
            cache_vars = {n: options.__dict__[n] for o, n in installer.knobs()
                          if n in options.__dict__}
            write_cache(cache_vars)

        ca.install_step_0(False, None, options)

        # Now put the CA cert where other instances exepct it
        ca_instance = cainstance.CAInstance(realm_name, certs.NSS_DIR)
        ca_instance.publish_ca_cert(CACERT)
    else:
        # Put the CA cert where other instances expect it
        x509.write_certificate(http_ca_cert, CACERT)
        os.chmod(CACERT, 0o444)

    # we now need to enable ssl on the ds
    ds.enable_ssl()

    krb = krbinstance.KrbInstance(fstore)
    if options.pkinit_cert_files:
        krb.create_instance(realm_name, host_name, domain_name,
                            dm_password, master_password,
                            setup_pkinit=not options.no_pkinit,
                            pkcs12_info=pkinit_pkcs12_info,
                            subject_base=options.subject)
    else:
        krb.create_instance(realm_name, host_name, domain_name,
                            dm_password, master_password,
                            setup_pkinit=not options.no_pkinit,
                            subject_base=options.subject)

    if setup_ca:
        ca.install_step_1(False, None, options)

    # The DS instance is created before the keytab, add the SSL cert we
    # generated
    ds.add_cert_to_service()

    memcache = memcacheinstance.MemcacheInstance()
    memcache.create_instance('MEMCACHE', host_name, dm_password,
                             ipautil.realm_to_suffix(realm_name))

    otpd = otpdinstance.OtpdInstance()
    otpd.create_instance('OTPD', host_name, dm_password,
                         ipautil.realm_to_suffix(realm_name))

    custodia = custodiainstance.CustodiaInstance(host_name, realm_name)
    custodia.create_instance(dm_password)

    # Create a HTTP instance
    http = httpinstance.HTTPInstance(fstore)
    if options.http_cert_files:
        http.create_instance(
            realm_name, host_name, domain_name, dm_password,
            pkcs12_info=http_pkcs12_info, subject_base=options.subject,
            auto_redirect=not options.no_ui_redirect,
            ca_is_configured=setup_ca)
    else:
        http.create_instance(
            realm_name, host_name, domain_name, dm_password,
            subject_base=options.subject,
            auto_redirect=not options.no_ui_redirect,
            ca_is_configured=setup_ca)
    tasks.restore_context(paths.CACHE_IPA_SESSIONS)

    # Export full CA chain
    ca_db = certs.CertDB(realm_name)
    os.chmod(CACERT, 0o644)
    ca_db.publish_ca_cert(CACERT)

    set_subject_in_config(realm_name, dm_password,
                          ipautil.realm_to_suffix(realm_name), options.subject)

    # Apply any LDAP updates. Needs to be done after the configuration file
    # is created
    service.print_msg("Applying LDAP updates")
    ds.apply_updates()

    # Restart ds and krb after configurations have been changed
    service.print_msg("Restarting the directory server")
    ds.restart()

    service.print_msg("Restarting the KDC")
    krb.restart()

    if setup_ca:
        services.knownservices['pki_tomcatd'].restart('pki-tomcat')

    api.Backend.ldap2.connect(autobind=True)
    if options.setup_dns:
        dns.install(False, False, options)
    else:
        # Create a BIND instance
        bind = bindinstance.BindInstance(fstore, dm_password)
        bind.setup(host_name, ip_addresses, realm_name,
                   domain_name, (), 'first', (),
                   zonemgr=options.zonemgr,
                   no_dnssec_validation=options.no_dnssec_validation)
        bind.create_file_with_system_records()

    # Restart httpd to pick up the new IPA configuration
    service.print_msg("Restarting the web server")
    http.restart()

    # update DNA shared config entry is done as far as possible
    # from restart to avoid waiting for its creation
    ds.update_dna_shared_config()

    # Set the admin user kerberos password
    ds.change_admin_password(admin_password)

    # Call client install script
    service.print_msg("Configuring client side components")
    try:
        args = [paths.IPA_CLIENT_INSTALL, "--on-master", "--unattended",
                "--domain", domain_name, "--server", host_name,
                "--realm", realm_name, "--hostname", host_name]
        if options.no_dns_sshfp:
            args.append("--no-dns-sshfp")
        if options.ssh_trust_dns:
            args.append("--ssh-trust-dns")
        if options.no_ssh:
            args.append("--no-ssh")
        if options.no_sshd:
            args.append("--no-sshd")
        if options.mkhomedir:
            args.append("--mkhomedir")
        run(args, redirect_output=True)
        print()
    except Exception as e:
        sys.exit("Configuration of client side components failed!")

    # Everything installed properly, activate ipa service.
    services.knownservices.ipa.enable()

    print("======================================="
          "=======================================")
    print("Setup complete")
    print("")
    print("Next steps:")
    print("\t1. You must make sure these network ports are open:")
    print("\t\tTCP Ports:")
    print("\t\t  * 80, 443: HTTP/HTTPS")
    print("\t\t  * 389, 636: LDAP/LDAPS")
    print("\t\t  * 88, 464: kerberos")
    if options.setup_dns:
        print("\t\t  * 53: bind")
    print("\t\tUDP Ports:")
    print("\t\t  * 88, 464: kerberos")
    if options.setup_dns:
        print("\t\t  * 53: bind")
    if not options.no_ntp:
        print("\t\t  * 123: ntp")
    print("")
    print("\t2. You can now obtain a kerberos ticket using the command: "
          "'kinit admin'")
    print("\t   This ticket will allow you to use the IPA tools (e.g., ipa "
          "user-add)")
    print("\t   and the web user interface.")

    if not services.knownservices.ntpd.is_running():
        print("\t3. Kerberos requires time synchronization between clients")
        print("\t   and servers for correct operation. You should consider "
              "enabling ntpd.")

    print("")
    if setup_ca:
        print(("Be sure to back up the CA certificates stored in " +
              paths.CACERT_P12))
        print("These files are required to create replicas. The password for "
              "these")
        print("files is the Directory Manager password")
    else:
        print("In order for Firefox autoconfiguration to work you will need to")
        print("use a SSL signing certificate. See the IPA documentation for "
              "more details.")

    if ipautil.file_exists(paths.ROOT_IPA_CACHE):
        os.remove(paths.ROOT_IPA_CACHE)
Example #32
0
def install(installer):
    options = installer
    fstore = installer._fstore
    sstore = installer._sstore
    dirsrv_pkcs12_info = installer._dirsrv_pkcs12_info
    http_pkcs12_info = installer._http_pkcs12_info
    pkinit_pkcs12_info = installer._pkinit_pkcs12_info
    http_ca_cert = installer._ca_cert

    realm_name = options.realm_name
    domain_name = options.domain_name
    dm_password = options.dm_password
    master_password = options.master_password
    admin_password = options.admin_password
    host_name = options.host_name
    ip_addresses = options.ip_addresses
    setup_ca = options.setup_ca

    # Installation has started. No IPA sysrestore items are restored in case of
    # failure to enable root cause investigation
    installer._installation_cleanup = False

    if installer.interactive:
        print("")
        print("The following operations may take some minutes to complete.")
        print("Please wait until the prompt is returned.")
        print("")

    # set hostname (transient and static) if user instructed us to do so
    if options._host_name_overridden:
        tasks.backup_hostname(fstore, sstore)
        tasks.set_hostname(host_name)

    if installer._update_hosts_file:
        update_hosts_file(ip_addresses, host_name, fstore)

    # Create a directory server instance
    if not options.external_cert_files:
        # We have to sync time before certificate handling on master.
        # As chrony configuration is moved from client here, unconfiguration of
        # chrony will be handled here in uninstall() method as well by invoking
        # the ipa-server-install --uninstall
        if not options.no_ntp:
            if not ipaclient.install.client.sync_time(options, fstore, sstore):
                print("Warning: IPA was unable to sync time with chrony!")
                print("         Time synchronization is required for IPA "
                      "to work correctly")

        if options.dirsrv_cert_files:
            ds = dsinstance.DsInstance(fstore=fstore,
                                       domainlevel=options.domainlevel,
                                       config_ldif=options.dirsrv_config_file)
            installer._ds = ds
            ds.create_instance(realm_name,
                               host_name,
                               domain_name,
                               dm_password,
                               dirsrv_pkcs12_info,
                               idstart=options.idstart,
                               idmax=options.idmax,
                               subject_base=options.subject_base,
                               ca_subject=options.ca_subject,
                               hbac_allow=not options.no_hbac_allow,
                               setup_pkinit=not options.no_pkinit)
        else:
            ds = dsinstance.DsInstance(fstore=fstore,
                                       domainlevel=options.domainlevel,
                                       config_ldif=options.dirsrv_config_file)
            installer._ds = ds
            ds.create_instance(realm_name,
                               host_name,
                               domain_name,
                               dm_password,
                               idstart=options.idstart,
                               idmax=options.idmax,
                               subject_base=options.subject_base,
                               ca_subject=options.ca_subject,
                               hbac_allow=not options.no_hbac_allow,
                               setup_pkinit=not options.no_pkinit)

    else:
        api.Backend.ldap2.connect()
        ds = dsinstance.DsInstance(fstore=fstore,
                                   domainlevel=options.domainlevel)
        installer._ds = ds
        ds.init_info(realm_name,
                     host_name,
                     domain_name,
                     dm_password,
                     options.subject_base,
                     options.ca_subject,
                     1101,
                     1100,
                     None,
                     setup_pkinit=not options.no_pkinit)

    krb = krbinstance.KrbInstance(fstore)
    if not options.external_cert_files:
        krb.create_instance(realm_name,
                            host_name,
                            domain_name,
                            dm_password,
                            master_password,
                            setup_pkinit=not options.no_pkinit,
                            pkcs12_info=pkinit_pkcs12_info,
                            subject_base=options.subject_base)
    else:
        krb.init_info(realm_name,
                      host_name,
                      setup_pkinit=not options.no_pkinit,
                      subject_base=options.subject_base)

    custodia = custodiainstance.get_custodia_instance(
        options, custodiainstance.CustodiaModes.FIRST_MASTER)
    custodia.create_instance()

    if setup_ca:
        if not options.external_cert_files and options.external_ca:
            # stage 1 of external CA installation
            options.realm_name = realm_name
            options.domain_name = domain_name
            options.master_password = master_password
            options.dm_password = dm_password
            options.admin_password = admin_password
            options.host_name = host_name
            options.reverse_zones = dns.reverse_zones
            cache_vars = {
                n: options.__dict__[n]
                for o, n in installer.knobs() if n in options.__dict__
            }
            write_cache(cache_vars)

        ca.install_step_0(False, None, options, custodia=custodia)
    else:
        # Put the CA cert where other instances expect it
        x509.write_certificate(http_ca_cert, paths.IPA_CA_CRT)
        os.chmod(paths.IPA_CA_CRT, 0o444)

        if not options.no_pkinit:
            x509.write_certificate(http_ca_cert, paths.KDC_CA_BUNDLE_PEM)
        else:
            with open(paths.KDC_CA_BUNDLE_PEM, 'w'):
                pass
        os.chmod(paths.KDC_CA_BUNDLE_PEM, 0o444)

        x509.write_certificate(http_ca_cert, paths.CA_BUNDLE_PEM)
        os.chmod(paths.CA_BUNDLE_PEM, 0o444)

    # we now need to enable ssl on the ds
    ds.enable_ssl()

    if setup_ca:
        ca.install_step_1(False, None, options, custodia=custodia)

    otpd = otpdinstance.OtpdInstance()
    otpd.create_instance('OTPD', host_name,
                         ipautil.realm_to_suffix(realm_name))

    # Create a HTTP instance
    http = httpinstance.HTTPInstance(fstore)
    if options.http_cert_files:
        http.create_instance(realm_name,
                             host_name,
                             domain_name,
                             dm_password,
                             pkcs12_info=http_pkcs12_info,
                             subject_base=options.subject_base,
                             auto_redirect=not options.no_ui_redirect,
                             ca_is_configured=setup_ca)
    else:
        http.create_instance(realm_name,
                             host_name,
                             domain_name,
                             dm_password,
                             subject_base=options.subject_base,
                             auto_redirect=not options.no_ui_redirect,
                             ca_is_configured=setup_ca)
    tasks.restore_context(paths.CACHE_IPA_SESSIONS)

    ca.set_subject_base_in_config(options.subject_base)

    # configure PKINIT now that all required services are in place
    krb.enable_ssl()

    # Apply any LDAP updates. Needs to be done after the configuration file
    # is created. DS is restarted in the process.
    service.print_msg("Applying LDAP updates")
    ds.apply_updates()

    # Restart krb after configurations have been changed
    service.print_msg("Restarting the KDC")
    krb.restart()

    if options.setup_kra:
        kra.install(api, None, options, custodia=custodia)

    if options.setup_dns:
        dns.install(False, False, options)

    if options.setup_adtrust:
        adtrust.install(False, options, fstore, api)

    # Set the admin user kerberos password
    ds.change_admin_password(admin_password)

    # Call client install script
    service.print_msg("Configuring client side components")
    try:
        args = [
            paths.IPA_CLIENT_INSTALL, "--on-master", "--unattended",
            "--domain", domain_name, "--server", host_name, "--realm",
            realm_name, "--hostname", host_name, "--no-ntp"
        ]
        if options.no_dns_sshfp:
            args.append("--no-dns-sshfp")
        if options.ssh_trust_dns:
            args.append("--ssh-trust-dns")
        if options.no_ssh:
            args.append("--no-ssh")
        if options.no_sshd:
            args.append("--no-sshd")
        if options.mkhomedir:
            args.append("--mkhomedir")
        start = time.time()
        run(args, redirect_output=True)
        dur = time.time() - start
        logger.debug("Client install duration: %0.3f",
                     dur,
                     extra={'timing': ('clientinstall', None, None, dur)})
        print()
    except Exception:
        raise ScriptError("Configuration of client side components failed!")

    # Enable configured services and update DNS SRV records
    service.enable_services(host_name)
    api.Command.dns_update_system_records()

    if not options.setup_dns:
        # After DNS and AD trust are configured and services are
        # enabled, create a dummy instance to dump DNS configuration.
        bind = bindinstance.BindInstance(fstore)
        bind.create_file_with_system_records()

    # Everything installed properly, activate ipa service.
    services.knownservices.ipa.enable()

    print("======================================="
          "=======================================")
    print("Setup complete")
    print("")
    print("Next steps:")
    print("\t1. You must make sure these network ports are open:")
    print("\t\tTCP Ports:")
    print("\t\t  * 80, 443: HTTP/HTTPS")
    print("\t\t  * 389, 636: LDAP/LDAPS")
    print("\t\t  * 88, 464: kerberos")
    if options.setup_dns:
        print("\t\t  * 53: bind")
    print("\t\tUDP Ports:")
    print("\t\t  * 88, 464: kerberos")
    if options.setup_dns:
        print("\t\t  * 53: bind")
    if not options.no_ntp:
        print("\t\t  * 123: ntp")
    print("")
    print("\t2. You can now obtain a kerberos ticket using the command: "
          "'kinit admin'")
    print("\t   This ticket will allow you to use the IPA tools (e.g., ipa "
          "user-add)")
    print("\t   and the web user interface.")

    if not services.knownservices.chronyd.is_running():
        print("\t3. Kerberos requires time synchronization between clients")
        print("\t   and servers for correct operation. You should consider "
              "enabling chronyd.")

    print("")
    if setup_ca:
        print(("Be sure to back up the CA certificates stored in " +
               paths.CACERT_P12))
        print("These files are required to create replicas. The password for "
              "these")
        print("files is the Directory Manager password")

    if os.path.isfile(paths.ROOT_IPA_CACHE):
        os.remove(paths.ROOT_IPA_CACHE)
Example #33
0
    def create_db(self, user=None, group=None, mode=None, backup=False):
        """Create cert DB

        :param user: User owner the secdir
        :param group: Group owner of the secdir
        :param mode: Mode of the secdir
        :param backup: Backup the sedir files
        """
        if mode is not None:
            dirmode = mode
            filemode = mode & 0o666
            pwdfilemode = mode & 0o660
        else:
            dirmode = 0o750
            filemode = 0o640
            pwdfilemode = 0o640

        uid = -1
        gid = -1
        if user is not None:
            uid = pwd.getpwnam(user).pw_uid
        if group is not None:
            gid = grp.getgrnam(group).gr_gid

        if backup:
            for filename in self.backup_filenames:
                ipautil.backup_file(filename)

        if not os.path.exists(self.secdir):
            os.makedirs(self.secdir, dirmode)

        if not os.path.exists(self.pwd_file):
            # Create the password file for this db
            with io.open(os.open(self.pwd_file,
                                 os.O_CREAT | os.O_WRONLY,
                                 pwdfilemode), 'w', closefd=True) as f:
                f.write(ipautil.ipa_generate_password())
                # flush and sync tempfile inode
                f.flush()
                os.fsync(f.fileno())

        # In case dbtype is auto, let certutil decide which type of DB
        # to create.
        if self.dbtype == 'auto':
            dbdir = self.secdir
        else:
            dbdir = '{}:{}'.format(self.dbtype, self.secdir)
        args = [
            paths.CERTUTIL,
            '-d', dbdir,
            '-N',
            '-f', self.pwd_file,
            # -@ in case it's an old db and it must be migrated
            '-@', self.pwd_file,
        ]
        ipautil.run(args, stdin=None, cwd=self.secdir)
        self._set_filenames(self._detect_dbtype())
        if self.filenames is None:
            # something went wrong...
            raise ValueError(
                "Failed to create NSSDB at '{}'".format(self.secdir)
            )

        # Finally fix up perms
        os.chown(self.secdir, uid, gid)
        os.chmod(self.secdir, dirmode)
        tasks.restore_context(self.secdir, force=True)
        for filename in self.filenames:
            if os.path.exists(filename):
                os.chown(filename, uid, gid)
                if filename == self.pwd_file:
                    new_mode = pwdfilemode
                else:
                    new_mode = filemode
                os.chmod(filename, new_mode)
                tasks.restore_context(filename, force=True)
Example #34
0
def install(options):
    global dirsrv_pkcs12_info
    global http_pkcs12_info
    global pkinit_pkcs12_info
    global external_cert_file
    global external_ca_file
    global http_ca_cert

    realm_name = options.realm_name
    domain_name = options.domain_name
    dm_password = options.dm_password
    master_password = options.master_password
    admin_password = options.admin_password
    host_name = options.host_name
    ip_addresses = options.ip_address
    setup_ca = options.setup_ca
    setup_kra = options.setup_kra

    global ds
    global installation_cleanup

    # Installation has started. No IPA sysrestore items are restored in case of
    # failure to enable root cause investigation
    installation_cleanup = False

    # Configuration for ipalib, we will bootstrap and finalize later, after
    # we are sure we have the configuration file ready.
    cfg = dict(
        context='installer',
        in_server=True,
        debug=options.debug
    )

    # Figure out what external CA step we're in. See cainstance.py for more
    # info on the 3 states.
    if options.external_cert_files:
        external = 2
    elif options.external_ca:
        external = 1
    else:
        external = 0

    # Create the management framework config file and finalize api
    target_fname = paths.IPA_DEFAULT_CONF
    fd = open(target_fname, "w")
    fd.write("[global]\n")
    fd.write("host=%s\n" % host_name)
    fd.write("basedn=%s\n" % ipautil.realm_to_suffix(realm_name))
    fd.write("realm=%s\n" % realm_name)
    fd.write("domain=%s\n" % domain_name)
    fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % format_netloc(host_name))
    fd.write("ldap_uri=ldapi://%%2fvar%%2frun%%2fslapd-%s.socket\n" %
             installutils.realm_to_serverid(realm_name))
    if setup_ca:
        fd.write("enable_ra=True\n")
        fd.write("ra_plugin=dogtag\n")
        fd.write("dogtag_version=%s\n" %
                 dogtag.install_constants.DOGTAG_VERSION)
    else:
        fd.write("enable_ra=False\n")
        fd.write("ra_plugin=none\n")
    fd.write("enable_kra=%s\n" % setup_kra)
    fd.write("mode=production\n")
    fd.close()

    # Must be readable for everyone
    os.chmod(target_fname, 0644)

    if not options.unattended:
        print ""
        print "The following operations may take some minutes to complete."
        print "Please wait until the prompt is returned."
        print ""

    system_hostname = get_fqdn()
    if host_name != system_hostname:
        root_logger.debug("Chosen hostname (%s) differs from system hostname "
                          "(%s) - change it" % (host_name, system_hostname))
        # configure /etc/sysconfig/network to contain the custom hostname
        tasks.backup_and_replace_hostname(fstore, sstore, host_name)
        # update `api.env.ca_host` to correct hostname
        # https://fedorahosted.org/freeipa/ticket/4936
        api.env.ca_host = host_name

    api.bootstrap(**cfg)
    if setup_ca:
        # ensure profile backend is available
        import ipaserver.plugins.dogtag
    api.finalize()

    # Create DS user/group if it doesn't exist yet
    dsinstance.create_ds_user()

    # Create a directory server instance
    if external != 2:
        # Configure ntpd
        if options.conf_ntp:
            ipaclient.ntpconf.force_ntpd(sstore)
            ntp = ntpinstance.NTPInstance(fstore)
            if not ntp.is_configured():
                ntp.create_instance()

        if options.dirsrv_cert_files:
            ds = dsinstance.DsInstance(fstore=fstore,
                                       domainlevel=options.domainlevel)
            ds.create_instance(realm_name, host_name, domain_name,
                               dm_password, dirsrv_pkcs12_info,
                               idstart=options.idstart, idmax=options.idmax,
                               subject_base=options.subject,
                               hbac_allow=not options.hbac_allow)
        else:
            ds = dsinstance.DsInstance(fstore=fstore,
                                       domainlevel=options.domainlevel)
            ds.create_instance(realm_name, host_name, domain_name,
                               dm_password,
                               idstart=options.idstart, idmax=options.idmax,
                               subject_base=options.subject,
                               hbac_allow=not options.hbac_allow)
    else:
        ds = dsinstance.DsInstance(fstore=fstore,
                                   domainlevel=options.domainlevel)
        ds.init_info(
            realm_name, host_name, domain_name, dm_password,
            options.subject, 1101, 1100, None)

    if setup_ca:
        ca = cainstance.CAInstance(realm_name, certs.NSS_DIR,
                                   dogtag_constants=dogtag.install_constants)
        if external == 0:
            ca.configure_instance(
                host_name, domain_name, dm_password, dm_password,
                subject_base=options.subject,
                ca_signing_algorithm=options.ca_signing_algorithm)
        elif external == 1:
            # stage 1 of external CA installation
            options.realm_name = realm_name
            options.domain_name = domain_name
            options.master_password = master_password
            options.dm_password = dm_password
            options.admin_password = admin_password
            options.host_name = host_name
            options.unattended = True
            options.forwarders = dns.dns_forwarders
            options.reverse_zones = dns.reverse_zones
            write_cache(vars(options))
            ca.configure_instance(
                host_name, domain_name, dm_password, dm_password,
                csr_file=paths.ROOT_IPA_CSR,
                subject_base=options.subject,
                ca_signing_algorithm=options.ca_signing_algorithm,
                ca_type=options.external_ca_type)
        else:
            # stage 2 of external CA installation
            ca.configure_instance(
                host_name, domain_name, dm_password, dm_password,
                cert_file=external_cert_file.name,
                cert_chain_file=external_ca_file.name,
                subject_base=options.subject,
                ca_signing_algorithm=options.ca_signing_algorithm)

        # Now put the CA cert where other instances exepct it
        ca.publish_ca_cert(CACERT)
    else:
        # Put the CA cert where other instances expect it
        x509.write_certificate(http_ca_cert, CACERT)
        os.chmod(CACERT, 0444)

    # we now need to enable ssl on the ds
    ds.enable_ssl()

    if setup_ca:
        # We need to ldap_enable the CA now that DS is up and running
        ca.ldap_enable('CA', host_name, dm_password,
                       ipautil.realm_to_suffix(realm_name),
                       ['caRenewalMaster'])

        # This is done within stopped_service context, which restarts CA
        ca.enable_client_auth_to_db(ca.dogtag_constants.CS_CFG_PATH)

    krb = krbinstance.KrbInstance(fstore)
    if options.pkinit_cert_files:
        krb.create_instance(realm_name, host_name, domain_name,
                            dm_password, master_password,
                            setup_pkinit=options.setup_pkinit,
                            pkcs12_info=pkinit_pkcs12_info,
                            subject_base=options.subject)
    else:
        krb.create_instance(realm_name, host_name, domain_name,
                            dm_password, master_password,
                            setup_pkinit=options.setup_pkinit,
                            subject_base=options.subject)

    # The DS instance is created before the keytab, add the SSL cert we
    # generated
    ds.add_cert_to_service()

    memcache = memcacheinstance.MemcacheInstance()
    memcache.create_instance('MEMCACHE', host_name, dm_password,
                             ipautil.realm_to_suffix(realm_name))

    otpd = otpdinstance.OtpdInstance()
    otpd.create_instance('OTPD', host_name, dm_password,
                         ipautil.realm_to_suffix(realm_name))

    # Create a HTTP instance
    http = httpinstance.HTTPInstance(fstore)
    if options.http_cert_files:
        http.create_instance(
            realm_name, host_name, domain_name, dm_password,
            pkcs12_info=http_pkcs12_info, subject_base=options.subject,
            auto_redirect=options.ui_redirect,
            ca_is_configured=setup_ca)
    else:
        http.create_instance(
            realm_name, host_name, domain_name, dm_password,
            subject_base=options.subject, auto_redirect=options.ui_redirect,
            ca_is_configured=setup_ca)
    tasks.restore_context(paths.CACHE_IPA_SESSIONS)

    # Export full CA chain
    ca_db = certs.CertDB(realm_name)
    os.chmod(CACERT, 0644)
    ca_db.publish_ca_cert(CACERT)

    set_subject_in_config(realm_name, dm_password,
                          ipautil.realm_to_suffix(realm_name), options.subject)

    # Apply any LDAP updates. Needs to be done after the configuration file
    # is created
    service.print_msg("Applying LDAP updates")
    ds.apply_updates()

    # Restart ds and krb after configurations have been changed
    service.print_msg("Restarting the directory server")
    ds.restart()

    service.print_msg("Restarting the KDC")
    krb.restart()

    if setup_ca:
        service.print_msg("Restarting the certificate server")
        ca.restart(dogtag.configured_constants().PKI_INSTANCE_NAME)

        service.print_msg("Importing certificate profiles")
        cainstance.import_included_profiles()

    if options.setup_dns:
        api.Backend.ldap2.connect(autobind=True)
        dns.install(False, False, options)
    else:
        # Create a BIND instance
        bind = bindinstance.BindInstance(fstore, dm_password)
        bind.setup(host_name, ip_addresses, realm_name,
                   domain_name, (), options.conf_ntp, (),
                   zonemgr=options.zonemgr, ca_configured=setup_ca,
                   no_dnssec_validation=options.no_dnssec_validation)
        bind.create_sample_bind_zone()

    # Restart httpd to pick up the new IPA configuration
    service.print_msg("Restarting the web server")
    http.restart()

    if setup_kra:
        kra.install(None, options, dm_password)

    # Set the admin user kerberos password
    ds.change_admin_password(admin_password)

    # Call client install script
    try:
        args = [paths.IPA_CLIENT_INSTALL, "--on-master", "--unattended",
                "--domain", domain_name, "--server", host_name,
                "--realm", realm_name, "--hostname", host_name]
        if not options.create_sshfp:
            args.append("--no-dns-sshfp")
        if options.trust_sshfp:
            args.append("--ssh-trust-dns")
        if not options.conf_ssh:
            args.append("--no-ssh")
        if not options.conf_sshd:
            args.append("--no-sshd")
        if options.mkhomedir:
            args.append("--mkhomedir")
        run(args)
    except Exception, e:
        sys.exit("Configuration of client side components failed!\n"
                 "ipa-client-install returned: " + str(e))
Example #35
0
def install(installer):
    options = installer
    fstore = installer._fstore
    sstore = installer._sstore
    dirsrv_pkcs12_info = installer._dirsrv_pkcs12_info
    http_pkcs12_info = installer._http_pkcs12_info
    pkinit_pkcs12_info = installer._pkinit_pkcs12_info
    http_ca_cert = installer._ca_cert

    realm_name = options.realm_name
    domain_name = options.domain_name
    dm_password = options.dm_password
    master_password = options.master_password
    admin_password = options.admin_password
    host_name = options.host_name
    ip_addresses = options.ip_addresses
    setup_ca = options.setup_ca

    # Installation has started. No IPA sysrestore items are restored in case of
    # failure to enable root cause investigation
    installer._installation_cleanup = False

    if installer.interactive:
        print("")
        print("The following operations may take some minutes to complete.")
        print("Please wait until the prompt is returned.")
        print("")

    # set hostname (transient and static) if user instructed us to do so
    if options._host_name_overridden:
        tasks.backup_hostname(fstore, sstore)
        tasks.set_hostname(host_name)

    if installer._update_hosts_file:
        update_hosts_file(ip_addresses, host_name, fstore)

    # Make sure tmpfiles dir exist before installing components
    tasks.create_tmpfiles_dirs()

    # Create a directory server instance
    if not options.external_cert_files:
        # Configure ntpd
        if not options.no_ntp:
            ipaclient.install.ntpconf.force_ntpd(sstore)
            ntp = ntpinstance.NTPInstance(fstore)
            if not ntp.is_configured():
                ntp.create_instance()

        if options.dirsrv_cert_files:
            ds = dsinstance.DsInstance(fstore=fstore,
                                       domainlevel=options.domainlevel,
                                       config_ldif=options.dirsrv_config_file)
            installer._ds = ds
            ds.create_instance(realm_name,
                               host_name,
                               domain_name,
                               dm_password,
                               dirsrv_pkcs12_info,
                               idstart=options.idstart,
                               idmax=options.idmax,
                               subject_base=options.subject_base,
                               ca_subject=options.ca_subject,
                               hbac_allow=not options.no_hbac_allow)
        else:
            ds = dsinstance.DsInstance(fstore=fstore,
                                       domainlevel=options.domainlevel,
                                       config_ldif=options.dirsrv_config_file)
            installer._ds = ds
            ds.create_instance(realm_name,
                               host_name,
                               domain_name,
                               dm_password,
                               idstart=options.idstart,
                               idmax=options.idmax,
                               subject_base=options.subject_base,
                               ca_subject=options.ca_subject,
                               hbac_allow=not options.no_hbac_allow)

        ntpinstance.ntp_ldap_enable(host_name, ds.suffix, realm_name)

    else:
        api.Backend.ldap2.connect()
        ds = dsinstance.DsInstance(fstore=fstore,
                                   domainlevel=options.domainlevel)
        installer._ds = ds
        ds.init_info(realm_name, host_name, domain_name, dm_password,
                     options.subject_base, options.ca_subject, 1101, 1100,
                     None)

    krb = krbinstance.KrbInstance(fstore)
    krb.create_instance(realm_name,
                        host_name,
                        domain_name,
                        dm_password,
                        master_password,
                        setup_pkinit=not options.no_pkinit,
                        pkcs12_info=pkinit_pkcs12_info,
                        subject_base=options.subject_base)

    if setup_ca:
        if not options.external_cert_files and options.external_ca:
            # stage 1 of external CA installation
            options.realm_name = realm_name
            options.domain_name = domain_name
            options.master_password = master_password
            options.dm_password = dm_password
            options.admin_password = admin_password
            options.host_name = host_name
            options.reverse_zones = dns.reverse_zones
            cache_vars = {
                n: options.__dict__[n]
                for o, n in installer.knobs() if n in options.__dict__
            }
            write_cache(cache_vars)

        ca.install_step_0(False, None, options)
    else:
        # Put the CA cert where other instances expect it
        x509.write_certificate(http_ca_cert, paths.IPA_CA_CRT)
        os.chmod(paths.IPA_CA_CRT, 0o444)

    # we now need to enable ssl on the ds
    ds.enable_ssl()

    if setup_ca:
        ca.install_step_1(False, None, options)

    otpd = otpdinstance.OtpdInstance()
    otpd.create_instance('OTPD', host_name,
                         ipautil.realm_to_suffix(realm_name))

    custodia = custodiainstance.CustodiaInstance(host_name, realm_name)
    custodia.create_instance()

    # Create a HTTP instance
    http = httpinstance.HTTPInstance(fstore)
    if options.http_cert_files:
        http.create_instance(realm_name,
                             host_name,
                             domain_name,
                             pkcs12_info=http_pkcs12_info,
                             subject_base=options.subject_base,
                             auto_redirect=not options.no_ui_redirect,
                             ca_is_configured=setup_ca)
    else:
        http.create_instance(realm_name,
                             host_name,
                             domain_name,
                             subject_base=options.subject_base,
                             auto_redirect=not options.no_ui_redirect,
                             ca_is_configured=setup_ca)
    tasks.restore_context(paths.CACHE_IPA_SESSIONS)

    ca.set_subject_base_in_config(options.subject_base)

    # configure PKINIT now that all required services are in place
    krb.enable_ssl()

    # Apply any LDAP updates. Needs to be done after the configuration file
    # is created. DS is restarted in the process.
    service.print_msg("Applying LDAP updates")
    ds.apply_updates()

    # Restart krb after configurations have been changed
    service.print_msg("Restarting the KDC")
    krb.restart()

    if options.setup_kra:
        kra.install(api, None, options)

    if options.setup_dns:
        dns.install(False, False, options)
    else:
        # Create a BIND instance
        bind = bindinstance.BindInstance(fstore)
        bind.setup(host_name,
                   ip_addresses,
                   realm_name,
                   domain_name, (),
                   'first', (),
                   zonemgr=options.zonemgr,
                   no_dnssec_validation=options.no_dnssec_validation)
        bind.create_file_with_system_records()

    if options.setup_adtrust:
        adtrust.install(False, options, fstore, api)

    # Set the admin user kerberos password
    ds.change_admin_password(admin_password)

    # Call client install script
    service.print_msg("Configuring client side components")
    try:
        args = [
            paths.IPA_CLIENT_INSTALL, "--on-master", "--unattended",
            "--domain", domain_name, "--server", host_name, "--realm",
            realm_name, "--hostname", host_name
        ]
        if options.no_dns_sshfp:
            args.append("--no-dns-sshfp")
        if options.ssh_trust_dns:
            args.append("--ssh-trust-dns")
        if options.no_ssh:
            args.append("--no-ssh")
        if options.no_sshd:
            args.append("--no-sshd")
        if options.mkhomedir:
            args.append("--mkhomedir")
        run(args, redirect_output=True)
        print()
    except Exception:
        raise ScriptError("Configuration of client side components failed!")

    # Make sure the files we crated in /var/run are recreated at startup
    tasks.configure_tmpfiles()

    # Everything installed properly, activate ipa service.
    services.knownservices.ipa.enable()

    print("======================================="
          "=======================================")
    print("Setup complete")
    print("")
    print("Next steps:")
    print("\t1. You must make sure these network ports are open:")
    print("\t\tTCP Ports:")
    print("\t\t  * 80, 443: HTTP/HTTPS")
    print("\t\t  * 389, 636: LDAP/LDAPS")
    print("\t\t  * 88, 464: kerberos")
    if options.setup_dns:
        print("\t\t  * 53: bind")
    print("\t\tUDP Ports:")
    print("\t\t  * 88, 464: kerberos")
    if options.setup_dns:
        print("\t\t  * 53: bind")
    if not options.no_ntp:
        print("\t\t  * 123: ntp")
    print("")
    print("\t2. You can now obtain a kerberos ticket using the command: "
          "'kinit admin'")
    print("\t   This ticket will allow you to use the IPA tools (e.g., ipa "
          "user-add)")
    print("\t   and the web user interface.")

    if not services.knownservices.ntpd.is_running():
        print("\t3. Kerberos requires time synchronization between clients")
        print("\t   and servers for correct operation. You should consider "
              "enabling ntpd.")

    print("")
    if setup_ca:
        print(("Be sure to back up the CA certificates stored in " +
               paths.CACERT_P12))
        print("These files are required to create replicas. The password for "
              "these")
        print("files is the Directory Manager password")
    else:
        print(
            "In order for Firefox autoconfiguration to work you will need to")
        print("use a SSL signing certificate. See the IPA documentation for "
              "more details.")

    if ipautil.file_exists(paths.ROOT_IPA_CACHE):
        os.remove(paths.ROOT_IPA_CACHE)
Example #36
0
    def ldif2db(self, instance, backend, online=True):
        '''
        Restore a LDIF backup of the data in this instance.

        If executed online create a task and wait for it to complete.
        '''
        logger.info('Restoring from %s in %s', backend, instance)

        cn = time.strftime('import_%Y_%m_%d_%H_%M_%S')
        dn = DN(('cn', cn), ('cn', 'import'), ('cn', 'tasks'), ('cn', 'config'))

        ldifdir = paths.SLAPD_INSTANCE_LDIF_DIR_TEMPLATE % instance
        ldifname = '%s-%s.ldif' % (instance, backend)
        ldiffile = os.path.join(ldifdir, ldifname)
        srcldiffile = os.path.join(self.dir, ldifname)

        if not os.path.exists(ldifdir):
            os.mkdir(ldifdir)
            os.chmod(ldifdir, 0o770)
            constants.DS_USER.chown(ldifdir)

        ipautil.backup_file(ldiffile)
        with open(ldiffile, 'w') as out_file:
            ldif_writer = ldif.LDIFWriter(out_file)
            with open(srcldiffile, 'rb') as in_file:
                ldif_parser = RemoveRUVParser(in_file, ldif_writer)
                ldif_parser.parse()

        # Make sure the modified ldiffile is owned by DS_USER
        constants.DS_USER.chown(ldiffile)

        if online:
            conn = self.get_connection()
            ent = conn.make_entry(
                dn,
                {
                    'objectClass': ['top', 'extensibleObject'],
                    'cn': [cn],
                    'nsFilename': [ldiffile],
                    'nsUseOneFile': ['true'],
                }
            )
            ent['nsInstance'] = [backend]

            try:
                conn.add_entry(ent)
            except Exception as e:
                logger.error("Unable to bind to LDAP server: %s", e)
                return

            logger.info("Waiting for LDIF to finish")
            wait_for_task(conn, dn)
        else:
            template_dir = paths.VAR_LOG_DIRSRV_INSTANCE_TEMPLATE % instance
            try:
                os.makedirs(template_dir)
            except OSError as e:
                pass

            constants.DS_USER.chown(template_dir)
            os.chmod(template_dir, 0o770)

            # Restore SELinux context of template_dir
            tasks.restore_context(template_dir)

            args = [paths.DSCTL,
                    instance,
                    'ldif2db',
                    backend,
                    ldiffile]
            result = run(args, raiseonerr=False)
            if result.returncode != 0:
                logger.critical("ldif2db failed: %s", result.error_log)
Example #37
0
def install(installer):
    options = installer
    fstore = installer._fstore
    sstore = installer._sstore
    dirsrv_pkcs12_info = installer._dirsrv_pkcs12_info
    http_pkcs12_info = installer._http_pkcs12_info
    pkinit_pkcs12_info = installer._pkinit_pkcs12_info
    http_ca_cert = installer._ca_cert

    realm_name = options.realm_name
    domain_name = options.domain_name
    dm_password = options.dm_password
    master_password = options.master_password
    admin_password = options.admin_password
    host_name = options.host_name
    ip_addresses = options.ip_addresses
    setup_ca = options.setup_ca

    # Installation has started. No IPA sysrestore items are restored in case of
    # failure to enable root cause investigation
    installer._installation_cleanup = False

    if installer.interactive:
        print("")
        print("The following operations may take some minutes to complete.")
        print("Please wait until the prompt is returned.")
        print("")

    # set hostname (transient and static) if user instructed us to do so
    if options._host_name_overridden:
        tasks.backup_hostname(fstore, sstore)
        tasks.set_hostname(host_name)

    if installer._update_hosts_file:
        update_hosts_file(ip_addresses, host_name, fstore)

    # Create a directory server instance
    if not options.external_cert_files:
        # Configure ntpd
        if not options.no_ntp:
            ipaclient.install.ntpconf.force_ntpd(sstore)
            ntp = ntpinstance.NTPInstance(fstore)
            if not ntp.is_configured():
                ntp.create_instance()

        if options.dirsrv_cert_files:
            ds = dsinstance.DsInstance(fstore=fstore,
                                       domainlevel=options.domainlevel,
                                       config_ldif=options.dirsrv_config_file)
            installer._ds = ds
            ds.create_instance(realm_name, host_name, domain_name,
                               dm_password, dirsrv_pkcs12_info,
                               idstart=options.idstart, idmax=options.idmax,
                               subject_base=options.subject_base,
                               ca_subject=options.ca_subject,
                               hbac_allow=not options.no_hbac_allow,
                               setup_pkinit=not options.no_pkinit)
        else:
            ds = dsinstance.DsInstance(fstore=fstore,
                                       domainlevel=options.domainlevel,
                                       config_ldif=options.dirsrv_config_file)
            installer._ds = ds
            ds.create_instance(realm_name, host_name, domain_name,
                               dm_password,
                               idstart=options.idstart, idmax=options.idmax,
                               subject_base=options.subject_base,
                               ca_subject=options.ca_subject,
                               hbac_allow=not options.no_hbac_allow,
                               setup_pkinit=not options.no_pkinit)

        ntpinstance.ntp_ldap_enable(host_name, ds.suffix, realm_name)

    else:
        api.Backend.ldap2.connect()
        ds = dsinstance.DsInstance(fstore=fstore,
                                   domainlevel=options.domainlevel)
        installer._ds = ds
        ds.init_info(
            realm_name, host_name, domain_name, dm_password,
            options.subject_base, options.ca_subject, 1101, 1100, None,
            setup_pkinit=not options.no_pkinit)

    krb = krbinstance.KrbInstance(fstore)
    if not options.external_cert_files:
        krb.create_instance(realm_name, host_name, domain_name,
                            dm_password, master_password,
                            setup_pkinit=not options.no_pkinit,
                            pkcs12_info=pkinit_pkcs12_info,
                            subject_base=options.subject_base)
    else:
        krb.init_info(realm_name, host_name,
                      setup_pkinit=not options.no_pkinit,
                      subject_base=options.subject_base)

    if setup_ca:
        if not options.external_cert_files and options.external_ca:
            # stage 1 of external CA installation
            options.realm_name = realm_name
            options.domain_name = domain_name
            options.master_password = master_password
            options.dm_password = dm_password
            options.admin_password = admin_password
            options.host_name = host_name
            options.reverse_zones = dns.reverse_zones
            cache_vars = {n: options.__dict__[n] for o, n in installer.knobs()
                          if n in options.__dict__}
            write_cache(cache_vars)

        ca.install_step_0(False, None, options)
    else:
        # Put the CA cert where other instances expect it
        x509.write_certificate(http_ca_cert, paths.IPA_CA_CRT)
        os.chmod(paths.IPA_CA_CRT, 0o444)

        if not options.no_pkinit:
            x509.write_certificate(http_ca_cert, paths.KDC_CA_BUNDLE_PEM)
        else:
            with open(paths.KDC_CA_BUNDLE_PEM, 'w'):
                pass
        os.chmod(paths.KDC_CA_BUNDLE_PEM, 0o444)

        x509.write_certificate(http_ca_cert, paths.CA_BUNDLE_PEM)
        os.chmod(paths.CA_BUNDLE_PEM, 0o444)

    # we now need to enable ssl on the ds
    ds.enable_ssl()

    if setup_ca:
        ca.install_step_1(False, None, options)

    otpd = otpdinstance.OtpdInstance()
    otpd.create_instance('OTPD', host_name,
                         ipautil.realm_to_suffix(realm_name))

    custodia = custodiainstance.CustodiaInstance(host_name, realm_name)
    custodia.create_instance()

    # Create a HTTP instance
    http = httpinstance.HTTPInstance(fstore)
    if options.http_cert_files:
        http.create_instance(
            realm_name, host_name, domain_name, dm_password,
            pkcs12_info=http_pkcs12_info, subject_base=options.subject_base,
            auto_redirect=not options.no_ui_redirect,
            ca_is_configured=setup_ca)
    else:
        http.create_instance(
            realm_name, host_name, domain_name, dm_password,
            subject_base=options.subject_base,
            auto_redirect=not options.no_ui_redirect,
            ca_is_configured=setup_ca)
    tasks.restore_context(paths.CACHE_IPA_SESSIONS)

    ca.set_subject_base_in_config(options.subject_base)

    # configure PKINIT now that all required services are in place
    krb.enable_ssl()

    # Apply any LDAP updates. Needs to be done after the configuration file
    # is created. DS is restarted in the process.
    service.print_msg("Applying LDAP updates")
    ds.apply_updates()

    # Restart krb after configurations have been changed
    service.print_msg("Restarting the KDC")
    krb.restart()

    if options.setup_kra:
        kra.install(api, None, options)

    if options.setup_dns:
        dns.install(False, False, options)
    else:
        # Create a BIND instance
        bind = bindinstance.BindInstance(fstore)
        bind.setup(host_name, ip_addresses, realm_name,
                   domain_name, (), 'first', (),
                   zonemgr=options.zonemgr,
                   no_dnssec_validation=options.no_dnssec_validation)
        bind.create_file_with_system_records()

    if options.setup_adtrust:
        adtrust.install(False, options, fstore, api)

    # Set the admin user kerberos password
    ds.change_admin_password(admin_password)

    # Call client install script
    service.print_msg("Configuring client side components")
    try:
        args = [paths.IPA_CLIENT_INSTALL, "--on-master", "--unattended",
                "--domain", domain_name, "--server", host_name,
                "--realm", realm_name, "--hostname", host_name]
        if options.no_dns_sshfp:
            args.append("--no-dns-sshfp")
        if options.ssh_trust_dns:
            args.append("--ssh-trust-dns")
        if options.no_ssh:
            args.append("--no-ssh")
        if options.no_sshd:
            args.append("--no-sshd")
        if options.mkhomedir:
            args.append("--mkhomedir")
        run(args, redirect_output=True)
        print()
    except Exception:
        raise ScriptError("Configuration of client side components failed!")

    # Everything installed properly, activate ipa service.
    services.knownservices.ipa.enable()

    print("======================================="
          "=======================================")
    print("Setup complete")
    print("")
    print("Next steps:")
    print("\t1. You must make sure these network ports are open:")
    print("\t\tTCP Ports:")
    print("\t\t  * 80, 443: HTTP/HTTPS")
    print("\t\t  * 389, 636: LDAP/LDAPS")
    print("\t\t  * 88, 464: kerberos")
    if options.setup_dns:
        print("\t\t  * 53: bind")
    print("\t\tUDP Ports:")
    print("\t\t  * 88, 464: kerberos")
    if options.setup_dns:
        print("\t\t  * 53: bind")
    if not options.no_ntp:
        print("\t\t  * 123: ntp")
    print("")
    print("\t2. You can now obtain a kerberos ticket using the command: "
          "'kinit admin'")
    print("\t   This ticket will allow you to use the IPA tools (e.g., ipa "
          "user-add)")
    print("\t   and the web user interface.")

    if not services.knownservices.ntpd.is_running():
        print("\t3. Kerberos requires time synchronization between clients")
        print("\t   and servers for correct operation. You should consider "
              "enabling ntpd.")

    print("")
    if setup_ca:
        print(("Be sure to back up the CA certificates stored in " +
              paths.CACERT_P12))
        print("These files are required to create replicas. The password for "
              "these")
        print("files is the Directory Manager password")

    if os.path.isfile(paths.ROOT_IPA_CACHE):
        os.remove(paths.ROOT_IPA_CACHE)
Example #38
0
    def ldif2db(self, instance, backend, online=True):
        '''
        Restore a LDIF backup of the data in this instance.

        If executed online create a task and wait for it to complete.
        '''
        logger.info('Restoring from %s in %s', backend, instance)

        cn = time.strftime('import_%Y_%m_%d_%H_%M_%S')
        dn = DN(('cn', cn), ('cn', 'import'), ('cn', 'tasks'), ('cn', 'config'))

        ldifdir = paths.SLAPD_INSTANCE_LDIF_DIR_TEMPLATE % instance
        ldifname = '%s-%s.ldif' % (instance, backend)
        ldiffile = os.path.join(ldifdir, ldifname)
        srcldiffile = os.path.join(self.dir, ldifname)

        if not os.path.exists(ldifdir):
            pent = pwd.getpwnam(constants.DS_USER)
            os.mkdir(ldifdir)
            os.chmod(ldifdir, 0o770)
            os.chown(ldifdir, pent.pw_uid, pent.pw_gid)

        ipautil.backup_file(ldiffile)
        with open(ldiffile, 'w') as out_file:
            ldif_writer = ldif.LDIFWriter(out_file)
            with open(srcldiffile, 'rb') as in_file:
                ldif_parser = RemoveRUVParser(in_file, ldif_writer)
                ldif_parser.parse()

        # Make sure the modified ldiffile is owned by DS_USER
        pent = pwd.getpwnam(constants.DS_USER)
        os.chown(ldiffile, pent.pw_uid, pent.pw_gid)

        if online:
            conn = self.get_connection()
            ent = conn.make_entry(
                dn,
                {
                    'objectClass': ['top', 'extensibleObject'],
                    'cn': [cn],
                    'nsFilename': [ldiffile],
                    'nsUseOneFile': ['true'],
                }
            )
            ent['nsInstance'] = [backend]

            try:
                conn.add_entry(ent)
            except Exception as e:
                logger.error("Unable to bind to LDAP server: %s", e)
                return

            logger.info("Waiting for LDIF to finish")
            wait_for_task(conn, dn)
        else:
            template_dir = paths.VAR_LOG_DIRSRV_INSTANCE_TEMPLATE % instance
            try:
                os.makedirs(template_dir)
            except OSError as e:
                pass
            # Restore SELinux context of template_dir
            tasks.restore_context(template_dir)

            args = [paths.LDIF2DB,
                    '-Z', instance,
                    '-i', ldiffile,
                    '-n', backend]
            result = run(args, raiseonerr=False)
            if result.returncode != 0:
                logger.critical("ldif2db failed: %s", result.error_log)
Example #39
0
    def create_db(self, user=None, group=None, mode=None, backup=False):
        """Create cert DB

        :param user: User owner the secdir
        :param group: Group owner of the secdir
        :param mode: Mode of the secdir
        :param backup: Backup the sedir files
        """
        if mode is not None:
            dirmode = mode
            filemode = mode & 0o666
            pwdfilemode = mode & 0o660
        else:
            dirmode = 0o750
            filemode = 0o640
            pwdfilemode = 0o640

        uid = -1
        gid = -1
        if user is not None:
            uid = pwd.getpwnam(user).pw_uid
        if group is not None:
            gid = grp.getgrnam(group).gr_gid

        if backup:
            for filename in self.backup_filenames:
                ipautil.backup_file(filename)

        if not os.path.exists(self.secdir):
            os.makedirs(self.secdir, dirmode)

        if not os.path.exists(self.pwd_file):
            # Create the password file for this db
            with io.open(os.open(self.pwd_file,
                                 os.O_CREAT | os.O_WRONLY,
                                 pwdfilemode), 'w', closefd=True) as f:
                f.write(ipautil.ipa_generate_password())
                f.flush()

        # In case dbtype is auto, let certutil decide which type of DB
        # to create.
        if self.dbtype == 'auto':
            dbdir = self.secdir
        else:
            dbdir = '{}:{}'.format(self.dbtype, self.secdir)
        args = [
            paths.CERTUTIL,
            '-d', dbdir,
            '-N',
            '-f', self.pwd_file,
            # -@ in case it's an old db and it must be migrated
            '-@', self.pwd_file,
        ]
        ipautil.run(args, stdin=None, cwd=self.secdir)
        self._set_filenames(self._detect_dbtype())
        if self.filenames is None:
            # something went wrong...
            raise ValueError(
                "Failed to create NSSDB at '{}'".format(self.secdir)
            )

        # Finally fix up perms
        os.chown(self.secdir, uid, gid)
        os.chmod(self.secdir, dirmode)
        tasks.restore_context(self.secdir, force=True)
        for filename in self.filenames:
            if os.path.exists(filename):
                os.chown(filename, uid, gid)
                if filename == self.pwd_file:
                    new_mode = pwdfilemode
                else:
                    new_mode = filemode
                os.chmod(filename, new_mode)
                tasks.restore_context(filename, force=True)