Exemple #1
0
def install_check(installer):
    options = installer
    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

    tasks.check_ipv6_stack_enabled()
    tasks.check_selinux_status()

    if options.master_password:
        msg = ("WARNING:\noption '-P/--master-password' is deprecated. "
               "KDC master password of sufficient strength is autogenerated "
               "during IPA server installation and should not be set "
               "manually.")
        print(textwrap.fill(msg, width=79, replace_whitespace=False))

    installer._installation_cleanup = True

    print("\nThe log file for this installation can be found in "
          "/var/log/ipaserver-install.log")
    if (not options.external_ca and not options.external_cert_files
            and is_ipa_configured()):
        installer._installation_cleanup = False
        raise ScriptError(
            "IPA server is already configured on this system.\n"
            "If you want to reinstall the IPA server, please uninstall "
            "it first using 'ipa-server-install --uninstall'.")

    client_fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
    if client_fstore.has_files():
        installer._installation_cleanup = False
        raise ScriptError(
            "IPA client is already configured on this system.\n"
            "Please uninstall it before configuring the IPA server, "
            "using 'ipa-client-install --uninstall'")

    fstore = sysrestore.FileStore(SYSRESTORE_DIR_PATH)
    sstore = sysrestore.StateFile(SYSRESTORE_DIR_PATH)

    # This will override any settings passed in on the cmdline
    if ipautil.file_exists(paths.ROOT_IPA_CACHE):
        if options.dm_password is not None:
            dm_password = options.dm_password
        else:
            dm_password = read_password("Directory Manager", confirm=False)
        if dm_password is None:
            raise ScriptError("Directory Manager password required")
        try:
            cache_vars = read_cache(dm_password)
            options.__dict__.update(cache_vars)
            if cache_vars.get('external_ca', False):
                options.external_ca = False
                options.interactive = False
        except Exception as e:
            raise ScriptError("Cannot process the cache file: %s" % str(e))

    # We only set up the CA if the PKCS#12 options are not given.
    if options.dirsrv_cert_files:
        setup_ca = False
    else:
        setup_ca = True
    options.setup_ca = setup_ca

    if not setup_ca and options.ca_subject:
        raise ScriptError(
            "--ca-subject cannot be used with CA-less installation")
    if not setup_ca and options.subject_base:
        raise ScriptError(
            "--subject-base cannot be used with CA-less installation")
    if not setup_ca and options.setup_kra:
        raise ScriptError(
            "--setup-kra cannot be used with CA-less installation")

    print("======================================="
          "=======================================")
    print("This program will set up the FreeIPA Server.")
    print("")
    print("This includes:")
    if setup_ca:
        print("  * Configure a stand-alone CA (dogtag) for certificate "
              "management")
    if not options.no_ntp:
        print("  * Configure the Network Time Daemon (ntpd)")
    print("  * Create and configure an instance of Directory Server")
    print("  * Create and configure a Kerberos Key Distribution Center (KDC)")
    print("  * Configure Apache (httpd)")
    if options.setup_kra:
        print("  * Configure KRA (dogtag) for secret management")
    if options.setup_dns:
        print("  * Configure DNS (bind)")
    if options.setup_adtrust:
        print("  * Configure Samba (smb) and winbind for managing AD trusts")
    if not options.no_pkinit:
        print("  * Configure the KDC to enable PKINIT")
    if options.no_ntp:
        print("")
        print("Excluded by options:")
        print("  * Configure the Network Time Daemon (ntpd)")
    if installer.interactive:
        print("")
        print("To accept the default shown in brackets, press the Enter key.")
    print("")

    if not options.external_cert_files:
        # Make sure the 389-ds ports are available
        check_dirsrv(not installer.interactive)

    if not options.no_ntp:
        try:
            ipaclient.install.ntpconf.check_timedate_services()
        except ipaclient.install.ntpconf.NTPConflictingService as e:
            print(
                ("WARNING: conflicting time&date synchronization service '%s'"
                 " will be disabled" % e.conflicting_service))
            print("in favor of ntpd")
            print("")
        except ipaclient.install.ntpconf.NTPConfigurationError:
            pass

    # Check to see if httpd is already configured to listen on 443
    if httpinstance.httpd_443_configured():
        raise ScriptError("Aborting installation")

    if not options.setup_dns and installer.interactive:
        if ipautil.user_input(
                "Do you want to configure integrated DNS "
                "(BIND)?", False):
            options.setup_dns = True
        print("")

    # check bind packages are installed
    if options.setup_dns:
        # Don't require an external DNS to say who we are if we are
        # setting up a local DNS server.
        options.no_host_dns = True

    # check the hostname is correctly configured, it must be as the kldap
    # utilities just use the hostname as returned by getaddrinfo to set
    # up some of the standard entries

    if options.host_name:
        host_default = options.host_name
    else:
        host_default = get_fqdn()

    try:
        if not installer.interactive or options.host_name:
            verify_fqdn(host_default, options.no_host_dns)
            host_name = host_default
        else:
            host_name = read_host_name(host_default, options.no_host_dns)
    except BadHostError as e:
        raise ScriptError(e)

    host_name = host_name.lower()
    root_logger.debug("will use host_name: %s\n" % host_name)

    if not options.domain_name:
        domain_name = read_domain_name(host_name[host_name.find(".") + 1:],
                                       not installer.interactive)
        root_logger.debug("read domain_name: %s\n" % domain_name)
        try:
            validate_domain_name(domain_name)
        except ValueError as e:
            raise ScriptError("Invalid domain name: %s" % unicode(e))
    else:
        domain_name = options.domain_name

    domain_name = domain_name.lower()

    if not options.realm_name:
        realm_name = read_realm_name(domain_name, not installer.interactive)
        root_logger.debug("read realm_name: %s\n" % realm_name)
    else:
        realm_name = options.realm_name.upper()

    if not options.subject_base:
        options.subject_base = installutils.default_subject_base(realm_name)

    if not options.ca_subject:
        options.ca_subject = \
            installutils.default_ca_subject_dn(options.subject_base)

    if options.http_cert_files:
        if options.http_pin is None:
            options.http_pin = installutils.read_password(
                "Enter Apache Server private key unlock",
                confirm=False,
                validate=False,
                retry=False)
            if options.http_pin is None:
                raise ScriptError(
                    "Apache Server private key unlock password required")
        http_pkcs12_file, http_pin, http_ca_cert = load_pkcs12(
            cert_files=options.http_cert_files,
            key_password=options.http_pin,
            key_nickname=options.http_cert_name,
            ca_cert_files=options.ca_cert_files,
            host_name=host_name)
        http_pkcs12_info = (http_pkcs12_file.name, http_pin)

    if options.dirsrv_cert_files:
        if options.dirsrv_pin is None:
            options.dirsrv_pin = read_password(
                "Enter Directory Server private key unlock",
                confirm=False,
                validate=False,
                retry=False)
            if options.dirsrv_pin is None:
                raise ScriptError(
                    "Directory Server private key unlock password required")
        dirsrv_pkcs12_file, dirsrv_pin, dirsrv_ca_cert = load_pkcs12(
            cert_files=options.dirsrv_cert_files,
            key_password=options.dirsrv_pin,
            key_nickname=options.dirsrv_cert_name,
            ca_cert_files=options.ca_cert_files,
            host_name=host_name)
        dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin)

    if options.pkinit_cert_files:
        if options.pkinit_pin is None:
            options.pkinit_pin = read_password(
                "Enter Kerberos KDC private key unlock",
                confirm=False,
                validate=False,
                retry=False)
            if options.pkinit_pin is None:
                raise ScriptError(
                    "Kerberos KDC private key unlock password required")
        pkinit_pkcs12_file, pkinit_pin, _pkinit_ca_cert = load_pkcs12(
            cert_files=options.pkinit_cert_files,
            key_password=options.pkinit_pin,
            key_nickname=options.pkinit_cert_name,
            ca_cert_files=options.ca_cert_files,
            host_name=host_name)
        pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin)

    if (options.http_cert_files and options.dirsrv_cert_files
            and http_ca_cert != dirsrv_ca_cert):
        raise ScriptError(
            "Apache Server SSL certificate and Directory Server SSL "
            "certificate are not signed by the same CA certificate")

    if not options.dm_password:
        dm_password = read_dm_password()

        if dm_password is None:
            raise ScriptError("Directory Manager password required")
    else:
        dm_password = options.dm_password

    if not options.master_password:
        master_password = ipa_generate_password()
    else:
        master_password = options.master_password

    if not options.admin_password:
        admin_password = read_admin_password()
        if admin_password is None:
            raise ScriptError("IPA admin password required")
    else:
        admin_password = options.admin_password

    # Configuration for ipalib, we will bootstrap and finalize later, after
    # we are sure we have the configuration file ready.
    cfg = dict(
        context='installer',
        confdir=paths.ETC_IPA,
        in_server=True,
        # make sure host name specified by user is used instead of default
        host=host_name,
    )
    if setup_ca:
        # we have an IPA-integrated CA
        cfg['ca_host'] = host_name

    # 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=10\n")
    else:
        fd.write("enable_ra=False\n")
        fd.write("ra_plugin=none\n")
    fd.write("mode=production\n")
    fd.close()

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

    api.bootstrap(**cfg)
    api.finalize()

    if setup_ca:
        ca.install_check(False, None, options)
    if options.setup_kra:
        kra.install_check(api, None, options)

    if options.setup_dns:
        dns.install_check(False, api, False, options, host_name)
        ip_addresses = dns.ip_addresses
    else:
        ip_addresses = get_server_ip_address(host_name,
                                             not installer.interactive, False,
                                             options.ip_addresses)

        # check addresses here, dns module is doing own check
        network_ip_address_warning(ip_addresses)
        broadcast_ip_address_warning(ip_addresses)

    if options.setup_adtrust:
        adtrust.install_check(False, options, api)

    # installer needs to update hosts file when DNS subsystem will be
    # installed or custom addresses are used
    if options.ip_addresses or options.setup_dns:
        installer._update_hosts_file = True

    print()
    print("The IPA Master Server will be configured with:")
    print("Hostname:       %s" % host_name)
    print("IP address(es): %s" % ", ".join(str(ip) for ip in ip_addresses))
    print("Domain name:    %s" % domain_name)
    print("Realm name:     %s" % realm_name)
    print()

    if options.setup_dns:
        print("BIND DNS server will be configured to serve IPA domain with:")
        print("Forwarders:       %s" %
              ("No forwarders" if not options.forwarders else ", ".join(
                  [str(ip) for ip in options.forwarders])))
        print('Forward policy:   %s' % options.forward_policy)
        print("Reverse zone(s):  %s" %
              ("No reverse zone" if options.no_reverse or not dns.reverse_zones
               else ", ".join(str(rz) for rz in dns.reverse_zones)))
        print()

    if not options.setup_adtrust:
        # If domain name and realm does not match, IPA server will not be able
        # to estabilish trust with Active Directory. Print big fat warning.

        realm_not_matching_domain = (domain_name.upper() != realm_name)

        if realm_not_matching_domain:
            print("WARNING: Realm name does not match the domain name.\n"
                  "You will not be able to estabilish trusts with Active "
                  "Directory unless\nthe realm name of the IPA server matches "
                  "its domain name.\n\n")

    if installer.interactive and not user_input(
            "Continue to configure the system with these values?", False):
        raise ScriptError("Installation aborted")

    options.realm_name = realm_name
    options.domain_name = domain_name
    options.dm_password = dm_password
    options.master_password = master_password
    options.admin_password = admin_password
    options._host_name_overridden = bool(options.host_name)
    options.host_name = host_name
    options.ip_addresses = ip_addresses

    installer._fstore = fstore
    installer._sstore = sstore
    installer._dirsrv_pkcs12_file = dirsrv_pkcs12_file
    installer._http_pkcs12_file = http_pkcs12_file
    installer._pkinit_pkcs12_file = pkinit_pkcs12_file
    installer._dirsrv_pkcs12_info = dirsrv_pkcs12_info
    installer._http_pkcs12_info = http_pkcs12_info
    installer._pkinit_pkcs12_info = pkinit_pkcs12_info
    installer._external_cert_file = external_cert_file
    installer._external_ca_file = external_ca_file
    installer._ca_cert = http_ca_cert
Exemple #2
0
def install_check(standalone, api, replica, options, hostname):
    global ip_addresses
    global reverse_zones
    fstore = sysrestore.FileStore(paths.SYSRESTORE)

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

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

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

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

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

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

    if options.disable_dnssec_master:
        _is_master()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    if reverse_zones:
        print("Using reverse zone(s) %s" % ', '.join(reverse_zones))
Exemple #3
0
def install_check(standalone, api, replica, options, hostname):
    global ip_addresses
    global reverse_zones
    fstore = sysrestore.FileStore(paths.SYSRESTORE)

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

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

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

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

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

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

    if options.disable_dnssec_master:
        _is_master()

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    if reverse_zones:
        print("Using reverse zone(s) %s" % ', '.join(reverse_zones))
Exemple #4
0
def install_check(installer):
    options = installer
    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

    if tasks.is_fips_enabled():
        raise RuntimeError(
            "Installing IPA server in FIPS mode is not supported")

    tasks.check_selinux_status()

    if options.master_password:
        msg = ("WARNING:\noption '-P/--master-password' is deprecated. "
               "KDC master password of sufficient strength is autogenerated "
               "during IPA server installation and should not be set "
               "manually.")
        print(textwrap.fill(msg, width=79, replace_whitespace=False))

    installer._installation_cleanup = True

    print("\nThe log file for this installation can be found in "
          "/var/log/ipaserver-install.log")
    if (not options.external_ca and not options.external_cert_files and
            is_ipa_configured()):
        installer._installation_cleanup = False
        raise ScriptError(
            "IPA server is already configured on this system.\n"
            "If you want to reinstall the IPA server, please uninstall "
            "it first using 'ipa-server-install --uninstall'.")

    client_fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
    if client_fstore.has_files():
        installer._installation_cleanup = False
        raise ScriptError(
            "IPA client is already configured on this system.\n"
            "Please uninstall it before configuring the IPA server, "
            "using 'ipa-client-install --uninstall'")

    fstore = sysrestore.FileStore(SYSRESTORE_DIR_PATH)
    sstore = sysrestore.StateFile(SYSRESTORE_DIR_PATH)

    # This will override any settings passed in on the cmdline
    if ipautil.file_exists(paths.ROOT_IPA_CACHE):
        if options.dm_password is not None:
            dm_password = options.dm_password
        else:
            dm_password = read_password("Directory Manager", confirm=False)
        if dm_password is None:
            raise ScriptError("Directory Manager password required")
        try:
            cache_vars = read_cache(dm_password)
            options.__dict__.update(cache_vars)
            if cache_vars.get('external_ca', False):
                options.external_ca = False
                options.interactive = False
        except Exception as e:
            raise ScriptError("Cannot process the cache file: %s" % str(e))

    # We only set up the CA if the PKCS#12 options are not given.
    if options.dirsrv_cert_files:
        setup_ca = False
    else:
        setup_ca = True
    options.setup_ca = setup_ca

    # first instance of KRA must be installed by ipa-kra-install
    options.setup_kra = False

    print("======================================="
          "=======================================")
    print("This program will set up the FreeIPA Server.")
    print("")
    print("This includes:")
    if setup_ca:
        print("  * Configure a stand-alone CA (dogtag) for certificate "
              "management")
    if not options.no_ntp:
        print("  * Configure the Network Time Daemon (ntpd)")
    print("  * Create and configure an instance of Directory Server")
    print("  * Create and configure a Kerberos Key Distribution Center (KDC)")
    print("  * Configure Apache (httpd)")
    if options.setup_dns:
        print("  * Configure DNS (bind)")
    if not options.no_pkinit:
        print("  * Configure the KDC to enable PKINIT")
    if options.no_ntp:
        print("")
        print("Excluded by options:")
        print("  * Configure the Network Time Daemon (ntpd)")
    if installer.interactive:
        print("")
        print("To accept the default shown in brackets, press the Enter key.")
    print("")

    if not options.external_cert_files:
        # Make sure the 389-ds ports are available
        check_dirsrv(not installer.interactive)

    if not options.no_ntp:
        try:
            ipaclient.install.ntpconf.check_timedate_services()
        except ipaclient.install.ntpconf.NTPConflictingService as e:
            print(("WARNING: conflicting time&date synchronization service '%s'"
                  " will be disabled" % e.conflicting_service))
            print("in favor of ntpd")
            print("")
        except ipaclient.install.ntpconf.NTPConfigurationError:
            pass

    # Check to see if httpd is already configured to listen on 443
    if httpinstance.httpd_443_configured():
        raise ScriptError("Aborting installation")

    if not options.setup_dns and installer.interactive:
        if ipautil.user_input("Do you want to configure integrated DNS "
                              "(BIND)?", False):
            options.setup_dns = True
        print("")

    # check bind packages are installed
    if options.setup_dns:
        # Don't require an external DNS to say who we are if we are
        # setting up a local DNS server.
        options.no_host_dns = True

    # check the hostname is correctly configured, it must be as the kldap
    # utilities just use the hostname as returned by getaddrinfo to set
    # up some of the standard entries

    if options.host_name:
        host_default = options.host_name
    else:
        host_default = get_fqdn()

    try:
        if not installer.interactive or options.host_name:
            verify_fqdn(host_default, options.no_host_dns)
            host_name = host_default
        else:
            host_name = read_host_name(host_default, options.no_host_dns)
    except BadHostError as e:
        raise ScriptError(e)

    host_name = host_name.lower()
    root_logger.debug("will use host_name: %s\n" % host_name)

    if not options.domain_name:
        domain_name = read_domain_name(host_name[host_name.find(".")+1:],
                                       not installer.interactive)
        root_logger.debug("read domain_name: %s\n" % domain_name)
        try:
            validate_domain_name(domain_name)
        except ValueError as e:
            raise ScriptError("Invalid domain name: %s" % unicode(e))
    else:
        domain_name = options.domain_name

    domain_name = domain_name.lower()

    if not options.realm_name:
        realm_name = read_realm_name(domain_name, not installer.interactive)
        root_logger.debug("read realm_name: %s\n" % realm_name)
    else:
        realm_name = options.realm_name.upper()

    if not options.subject:
        options.subject = DN(('O', realm_name))

    if options.http_cert_files:
        if options.http_pin is None:
            options.http_pin = installutils.read_password(
                "Enter Apache Server private key unlock",
                confirm=False, validate=False, retry=False)
            if options.http_pin is None:
                raise ScriptError(
                    "Apache Server private key unlock password required")
        http_pkcs12_file, http_pin, http_ca_cert = load_pkcs12(
            cert_files=options.http_cert_files,
            key_password=options.http_pin,
            key_nickname=options.http_cert_name,
            ca_cert_files=options.ca_cert_files,
            host_name=host_name)
        http_pkcs12_info = (http_pkcs12_file.name, http_pin)

    if options.dirsrv_cert_files:
        if options.dirsrv_pin is None:
            options.dirsrv_pin = read_password(
                "Enter Directory Server private key unlock",
                confirm=False, validate=False, retry=False)
            if options.dirsrv_pin is None:
                raise ScriptError(
                    "Directory Server private key unlock password required")
        dirsrv_pkcs12_file, dirsrv_pin, dirsrv_ca_cert = load_pkcs12(
            cert_files=options.dirsrv_cert_files,
            key_password=options.dirsrv_pin,
            key_nickname=options.dirsrv_cert_name,
            ca_cert_files=options.ca_cert_files,
            host_name=host_name)
        dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin)

    if options.pkinit_cert_files:
        if not options.no_pkinit:
            raise ScriptError("Cannot create KDC PKINIT certificate and use "
                              "provided external PKINIT certificate at the "
                              "same time. Please choose one of them.")

        if options.pkinit_pin is None:
            options.pkinit_pin = read_password(
                "Enter Kerberos KDC private key unlock",
                confirm=False, validate=False, retry=False)
            if options.pkinit_pin is None:
                raise ScriptError(
                    "Kerberos KDC private key unlock password required")
        pkinit_pkcs12_file, pkinit_pin, _pkinit_ca_cert = load_pkcs12(
            cert_files=options.pkinit_cert_files,
            key_password=options.pkinit_pin,
            key_nickname=options.pkinit_cert_name,
            ca_cert_files=options.ca_cert_files,
            host_name=host_name)
        pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin)

    if (options.http_cert_files and options.dirsrv_cert_files and
            http_ca_cert != dirsrv_ca_cert):
        raise ScriptError(
            "Apache Server SSL certificate and Directory Server SSL "
            "certificate are not signed by the same CA certificate")

    if not options.dm_password:
        dm_password = read_dm_password()

        if dm_password is None:
            raise ScriptError("Directory Manager password required")
    else:
        dm_password = options.dm_password

    if not options.master_password:
        master_password = ipa_generate_password()
    else:
        master_password = options.master_password

    if not options.admin_password:
        admin_password = read_admin_password()
        if admin_password is None:
            raise ScriptError("IPA admin password required")
    else:
        admin_password = options.admin_password

    # Configuration for ipalib, we will bootstrap and finalize later, after
    # we are sure we have the configuration file ready.
    cfg = dict(
        context='installer',
        confdir=paths.ETC_IPA,
        in_server=True,
        # make sure host name specified by user is used instead of default
        host=host_name,
    )
    if setup_ca:
        # we have an IPA-integrated CA
        cfg['ca_host'] = host_name

    # 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=10\n")
    else:
        fd.write("enable_ra=False\n")
        fd.write("ra_plugin=none\n")
    fd.write("mode=production\n")
    fd.close()

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

    api.bootstrap(**cfg)
    api.finalize()

    if setup_ca:
        ca.install_check(False, None, options)
        kra.install_check(api, None, options)

    if options.setup_dns:
        dns.install_check(False, api, False, options, host_name)
        ip_addresses = dns.ip_addresses
    else:
        ip_addresses = get_server_ip_address(host_name,
                                             not installer.interactive, False,
                                             options.ip_addresses)

        # check addresses here, dns module is doing own check
        network_ip_address_warning(ip_addresses)
        broadcast_ip_address_warning(ip_addresses)

    # installer needs to update hosts file when DNS subsystem will be
    # installed or custom addresses are used
    if options.ip_addresses or options.setup_dns:
        installer._update_hosts_file = True

    print()
    print("The IPA Master Server will be configured with:")
    print("Hostname:       %s" % host_name)
    print("IP address(es): %s" % ", ".join(str(ip) for ip in ip_addresses))
    print("Domain name:    %s" % domain_name)
    print("Realm name:     %s" % realm_name)
    print()

    if options.setup_dns:
        print("BIND DNS server will be configured to serve IPA domain with:")
        print("Forwarders:       %s" % (
            "No forwarders" if not options.forwarders
            else ", ".join([str(ip) for ip in options.forwarders])
        ))
        print('Forward policy:   %s' % options.forward_policy)
        print("Reverse zone(s):  %s" % (
            "No reverse zone" if options.no_reverse or not dns.reverse_zones
            else ", ".join(str(rz) for rz in dns.reverse_zones)
        ))
        print()

    # If domain name and realm does not match, IPA server will not be able
    # to estabilish trust with Active Directory. Print big fat warning.

    realm_not_matching_domain = (domain_name.upper() != realm_name)

    if realm_not_matching_domain:
        print("WARNING: Realm name does not match the domain name.\n"
              "You will not be able to estabilish trusts with Active "
              "Directory unless\nthe realm name of the IPA server matches "
              "its domain name.\n\n")

    if installer.interactive and not user_input(
            "Continue to configure the system with these values?", False):
        raise ScriptError("Installation aborted")

    options.realm_name = realm_name
    options.domain_name = domain_name
    options.dm_password = dm_password
    options.master_password = master_password
    options.admin_password = admin_password
    options._host_name_overridden = bool(options.host_name)
    options.host_name = host_name
    options.ip_addresses = ip_addresses

    installer._fstore = fstore
    installer._sstore = sstore
    installer._dirsrv_pkcs12_file = dirsrv_pkcs12_file
    installer._http_pkcs12_file = http_pkcs12_file
    installer._pkinit_pkcs12_file = pkinit_pkcs12_file
    installer._dirsrv_pkcs12_info = dirsrv_pkcs12_info
    installer._http_pkcs12_info = http_pkcs12_info
    installer._pkinit_pkcs12_info = pkinit_pkcs12_info
    installer._external_cert_file = external_cert_file
    installer._external_ca_file = external_ca_file
    installer._ca_cert = http_ca_cert