Imported Debian patch 4.8.10-2
This commit is contained in:
committed by
Mario Fetka
parent
8bc559c5a1
commit
358acdd85f
@@ -26,30 +26,34 @@ import shutil
|
||||
import socket
|
||||
import sys
|
||||
import tempfile
|
||||
import textwrap
|
||||
import time
|
||||
import traceback
|
||||
import warnings
|
||||
|
||||
# pylint: disable=import-error
|
||||
from six.moves.configparser import RawConfigParser
|
||||
from six.moves.urllib.parse import urlparse, urlunparse
|
||||
# pylint: enable=import-error
|
||||
from configparser import RawConfigParser
|
||||
from urllib.parse import urlparse, urlunparse
|
||||
|
||||
from ipalib import api, errors, x509
|
||||
from ipalib.constants import IPAAPI_USER
|
||||
from ipalib.install import certmonger, certstore, service, sysrestore
|
||||
from ipalib import sysrestore
|
||||
from ipalib.constants import IPAAPI_USER, MAXHOSTNAMELEN
|
||||
from ipalib.install import certmonger, certstore, service
|
||||
from ipalib.install import hostname as hostname_
|
||||
from ipalib.facts import is_ipa_client_configured, is_ipa_configured
|
||||
from ipalib.install.kinit import kinit_keytab, kinit_password
|
||||
from ipalib.install.service import enroll_only, prepare_only
|
||||
from ipalib.rpc import delete_persistent_client_session_data
|
||||
from ipalib.util import (
|
||||
normalize_hostname,
|
||||
no_matching_interface_for_ip_address_warning,
|
||||
validate_hostname,
|
||||
verify_host_resolvable,
|
||||
)
|
||||
from ipaplatform import services
|
||||
from ipaplatform.constants import constants
|
||||
from ipaplatform.paths import paths
|
||||
from ipaplatform.tasks import tasks
|
||||
from ipapython import certdb, kernel_keyring, ipaldap, ipautil
|
||||
from ipapython import certdb, kernel_keyring, ipaldap, ipautil, dnsutil
|
||||
from ipapython.admintool import ScriptError
|
||||
from ipapython.dn import DN
|
||||
from ipapython.install import typing
|
||||
@@ -64,8 +68,9 @@ from ipapython.ipautil import (
|
||||
from ipapython.ssh import SSHPublicKey
|
||||
from ipapython import version
|
||||
|
||||
from . import automount, ipadiscovery, timeconf, sssd
|
||||
from .ipachangeconf import IPAChangeConf
|
||||
from . import automount, timeconf, sssd
|
||||
from ipaclient import discovery
|
||||
from ipapython.ipachangeconf import IPAChangeConf
|
||||
|
||||
NoneType = type(None)
|
||||
|
||||
@@ -263,33 +268,33 @@ def delete_ipa_domain():
|
||||
"No access to the /etc/sssd/sssd.conf file.")
|
||||
|
||||
|
||||
def is_ipa_client_installed(fstore, on_master=False):
|
||||
def is_ipa_client_installed(on_master=False):
|
||||
"""
|
||||
Consider IPA client not installed if nothing is backed up
|
||||
and default.conf file does not exist. If on_master is set to True,
|
||||
the existence of default.conf file is not taken into consideration,
|
||||
since it has been already created by ipa-server-install.
|
||||
"""
|
||||
|
||||
installed = (
|
||||
fstore.has_files() or (
|
||||
not on_master and os.path.exists(paths.IPA_DEFAULT_CONF)
|
||||
)
|
||||
warnings.warn(
|
||||
"Use 'ipalib.facts.is_ipa_client_configured'",
|
||||
DeprecationWarning,
|
||||
stacklevel=2
|
||||
)
|
||||
|
||||
return installed
|
||||
return is_ipa_client_configured(on_master)
|
||||
|
||||
|
||||
def configure_nsswitch_database(fstore, database, services, preserve=True,
|
||||
append=True, default_value=()):
|
||||
"""
|
||||
This function was deprecated. Use ipaplatform.tasks.
|
||||
|
||||
Edits the specified nsswitch.conf database (e.g. passwd, group, sudoers)
|
||||
to use the specified service(s).
|
||||
|
||||
Arguments:
|
||||
fstore - FileStore to backup the nsswitch.conf
|
||||
database - database configuration that should be ammended,
|
||||
e.g. 'sudoers'
|
||||
e.g. 'sudoers'
|
||||
service - list of services that should be added, e.g. ['sss']
|
||||
preserve - if True, the already configured services will be preserved
|
||||
|
||||
@@ -299,51 +304,13 @@ def configure_nsswitch_database(fstore, database, services, preserve=True,
|
||||
the database is not mentioned in nsswitch.conf), e.g.
|
||||
['files']
|
||||
"""
|
||||
|
||||
# Backup the original version of nsswitch.conf, we're going to edit it now
|
||||
if not fstore.has_file(paths.NSSWITCH_CONF):
|
||||
fstore.backup_file(paths.NSSWITCH_CONF)
|
||||
|
||||
conf = IPAChangeConf("IPA Installer")
|
||||
conf.setOptionAssignment(':')
|
||||
|
||||
if preserve:
|
||||
# Read the existing configuration
|
||||
with open(paths.NSSWITCH_CONF, 'r') as f:
|
||||
opts = conf.parse(f)
|
||||
raw_database_entry = conf.findOpts(opts, 'option', database)[1]
|
||||
|
||||
# Detect the list of already configured services
|
||||
if not raw_database_entry:
|
||||
# If there is no database entry, database is not present in
|
||||
# the nsswitch.conf. Set the list of services to the
|
||||
# default list, if passed.
|
||||
configured_services = list(default_value)
|
||||
else:
|
||||
configured_services = raw_database_entry['value'].strip().split()
|
||||
|
||||
# Make sure no service is added if already mentioned in the list
|
||||
added_services = [s for s in services
|
||||
if s not in configured_services]
|
||||
|
||||
# Prepend / append the list of new services
|
||||
if append:
|
||||
new_value = ' ' + ' '.join(configured_services + added_services)
|
||||
else:
|
||||
new_value = ' ' + ' '.join(added_services + configured_services)
|
||||
|
||||
else:
|
||||
# Preserve not set, let's rewrite existing configuration
|
||||
new_value = ' ' + ' '.join(services)
|
||||
|
||||
# Set new services as sources for database
|
||||
opts = [
|
||||
conf.setOption(database, new_value),
|
||||
conf.emptyLine(),
|
||||
]
|
||||
|
||||
conf.changeConf(paths.NSSWITCH_CONF, opts)
|
||||
logger.info("Configured %s in %s", database, paths.NSSWITCH_CONF)
|
||||
warnings.warn(
|
||||
"Use ipaplatform.tasks.tasks.configure_nsswitch_database",
|
||||
DeprecationWarning,
|
||||
stacklevel=2
|
||||
)
|
||||
return tasks.configure_nsswitch_database(fstore, database, services,
|
||||
preserve, append, default_value)
|
||||
|
||||
|
||||
def configure_ipa_conf(
|
||||
@@ -662,13 +629,9 @@ def hardcode_ldap_server(cli_server):
|
||||
"hardcoded server name: %s", cli_server[0])
|
||||
|
||||
|
||||
def configure_krb5_conf(
|
||||
cli_realm, cli_domain, cli_server, cli_kdc, dnsok,
|
||||
filename, client_domain, client_hostname, force=False,
|
||||
configure_sssd=True):
|
||||
|
||||
# First, write a snippet to krb5.conf.d. Currently this doesn't support
|
||||
# templating, but that could be changed in the future.
|
||||
# Currently this doesn't support templating, but that could be changed in the
|
||||
# future. Note that this function is also called from %post.
|
||||
def configure_krb5_snippet():
|
||||
template = os.path.join(
|
||||
paths.USR_SHARE_IPA_CLIENT_DIR,
|
||||
os.path.basename(paths.KRB5_FREEIPA) + ".template"
|
||||
@@ -676,6 +639,16 @@ def configure_krb5_conf(
|
||||
shutil.copy(template, paths.KRB5_FREEIPA)
|
||||
os.chmod(paths.KRB5_FREEIPA, 0o644)
|
||||
|
||||
tasks.restore_context(paths.KRB5_FREEIPA)
|
||||
|
||||
|
||||
def configure_krb5_conf(
|
||||
cli_realm, cli_domain, cli_server, cli_kdc, dnsok,
|
||||
filename, client_domain, client_hostname, force=False,
|
||||
configure_sssd=True):
|
||||
# First, write a snippet to krb5.conf.d.
|
||||
configure_krb5_snippet()
|
||||
|
||||
# Then, perform the rest of our configuration into krb5.conf itself.
|
||||
krbconf = IPAChangeConf("IPA Installer")
|
||||
krbconf.setOptionAssignment((" = ", " "))
|
||||
@@ -807,7 +780,16 @@ def configure_krb5_conf(
|
||||
def configure_certmonger(
|
||||
fstore, subject_base, cli_realm, hostname, options, ca_enabled):
|
||||
|
||||
cmonger = services.knownservices.certmonger
|
||||
if not options.request_cert:
|
||||
# Conditionally restart certmonger to pick up the new IPA
|
||||
# configuration.
|
||||
try:
|
||||
cmonger.try_restart()
|
||||
except Exception as e:
|
||||
logger.error(
|
||||
"Failed to conditionally restart the %s daemon: %s",
|
||||
cmonger.service_name, str(e))
|
||||
return
|
||||
|
||||
if not ca_enabled:
|
||||
@@ -822,7 +804,6 @@ def configure_certmonger(
|
||||
# which principal name to use when requesting certs.
|
||||
certmonger.add_principal_to_cas(principal)
|
||||
|
||||
cmonger = services.knownservices.certmonger
|
||||
try:
|
||||
cmonger.enable()
|
||||
cmonger.start()
|
||||
@@ -947,9 +928,7 @@ def configure_sssd_conf(
|
||||
"Unable to activate the SUDO service in SSSD config.")
|
||||
|
||||
sssdconfig.activate_service('sudo')
|
||||
configure_nsswitch_database(
|
||||
fstore, 'sudoers', ['sss'],
|
||||
default_value=['files'])
|
||||
tasks.enable_sssd_sudo(fstore)
|
||||
|
||||
domain.add_provider('ipa', 'id')
|
||||
|
||||
@@ -1038,8 +1017,13 @@ def sssd_enable_service(sssdconfig, name):
|
||||
return sssdconfig.get_service(name)
|
||||
|
||||
|
||||
def sssd_enable_ifp(sssdconfig):
|
||||
def sssd_enable_ifp(sssdconfig, allow_httpd=False):
|
||||
"""Enable and configure libsss_simpleifp plugin
|
||||
|
||||
Allow the ``ipaapi`` user to access IFP. In case allow_httpd is true,
|
||||
the Apache HTTPd user is also allowed to access IFP. For smart card
|
||||
authentication, mod_lookup_identity must be allowed to access user
|
||||
information.
|
||||
"""
|
||||
service = sssd_enable_service(sssdconfig, 'ifp')
|
||||
if service is None:
|
||||
@@ -1058,6 +1042,8 @@ def sssd_enable_ifp(sssdconfig):
|
||||
uids.add('root')
|
||||
# allow IPA API to access IFP
|
||||
uids.add(IPAAPI_USER)
|
||||
if allow_httpd:
|
||||
uids.add(constants.HTTPD_USER)
|
||||
service.set_option('allowed_uids', ', '.join(sorted(uids)))
|
||||
sssdconfig.save_service(service)
|
||||
|
||||
@@ -1131,7 +1117,6 @@ def configure_ssh_config(fstore, options):
|
||||
changes['GlobalKnownHostsFile'] = paths.SSSD_PUBCONF_KNOWN_HOSTS
|
||||
if options.trust_sshfp:
|
||||
changes['VerifyHostKeyDNS'] = 'yes'
|
||||
changes['HostKeyAlgorithms'] = 'ssh-rsa,ssh-dss'
|
||||
|
||||
change_ssh_config(paths.SSH_CONFIG, changes, ['Host', 'Match'])
|
||||
logger.info('Configured %s', paths.SSH_CONFIG)
|
||||
@@ -1146,6 +1131,29 @@ def configure_sshd_config(fstore, options):
|
||||
|
||||
fstore.backup_file(paths.SSHD_CONFIG)
|
||||
|
||||
# If openssh-server >= 8.2, the config needs to go in a new snippet
|
||||
# in /etc/ssh/sshd_config.d/04-ipa.conf
|
||||
# instead of /etc/ssh/sshd_config file
|
||||
def sshd_version_supports_include():
|
||||
with open(paths.SSHD_CONFIG, 'r') as f:
|
||||
for line in f:
|
||||
if re.match(r"^Include\s", line):
|
||||
return True
|
||||
return False
|
||||
|
||||
if sshd_version_supports_include():
|
||||
create_sshd_ipa_config(options)
|
||||
else:
|
||||
modify_sshd_config(options)
|
||||
|
||||
if sshd.is_running():
|
||||
try:
|
||||
sshd.restart()
|
||||
except Exception as e:
|
||||
log_service_error(sshd.service_name, 'restart', e)
|
||||
|
||||
|
||||
def modify_sshd_config(options):
|
||||
changes = {
|
||||
'PubkeyAuthentication': 'yes',
|
||||
'KerberosAuthentication': 'no',
|
||||
@@ -1194,11 +1202,24 @@ def configure_sshd_config(fstore, options):
|
||||
change_ssh_config(paths.SSHD_CONFIG, changes, ['Match'])
|
||||
logger.info('Configured %s', paths.SSHD_CONFIG)
|
||||
|
||||
if sshd.is_running():
|
||||
try:
|
||||
sshd.restart()
|
||||
except Exception as e:
|
||||
log_service_error(sshd.service_name, 'restart', e)
|
||||
|
||||
def create_sshd_ipa_config(options):
|
||||
"""Add the IPA snippet for sshd"""
|
||||
sssd_sshd_options = ""
|
||||
if options.sssd and os.path.isfile(paths.SSS_SSH_AUTHORIZEDKEYS):
|
||||
sssd_sshd_options = textwrap.dedent("""\
|
||||
AuthorizedKeysCommand {}
|
||||
AuthorizedKeysCommandUser nobody
|
||||
""").format(paths.SSS_SSH_AUTHORIZEDKEYS)
|
||||
|
||||
ipautil.copy_template_file(
|
||||
os.path.join(paths.SSHD_IPA_CONFIG_TEMPLATE),
|
||||
paths.SSHD_IPA_CONFIG,
|
||||
dict(
|
||||
SSSD_SSHD_OPTIONS=sssd_sshd_options,
|
||||
)
|
||||
)
|
||||
logger.info('Configured %s', paths.SSHD_IPA_CONFIG)
|
||||
|
||||
|
||||
def configure_automount(options):
|
||||
@@ -1419,7 +1440,7 @@ def verify_dns_update(fqdn, ips):
|
||||
logger.debug('DNS resolver: Query: %s IN %s',
|
||||
fqdn, dns.rdatatype.to_text(record_type))
|
||||
try:
|
||||
answers = dns.resolver.query(fqdn, record_type)
|
||||
answers = dnsutil.resolve(fqdn, record_type)
|
||||
except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN):
|
||||
logger.debug('DNS resolver: No record.')
|
||||
except dns.resolver.NoNameservers:
|
||||
@@ -1439,10 +1460,9 @@ def verify_dns_update(fqdn, ips):
|
||||
missing_reverse = [str(ip) for ip in ips]
|
||||
for ip in ips:
|
||||
ip_str = str(ip)
|
||||
addr = dns.reversename.from_address(ip_str)
|
||||
logger.debug('DNS resolver: Query: %s IN PTR', addr)
|
||||
logger.debug('DNS resolver: Query: %s IN PTR', ip_str)
|
||||
try:
|
||||
answers = dns.resolver.query(addr, dns.rdatatype.PTR)
|
||||
answers = dnsutil.resolve_address(ip_str)
|
||||
except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN):
|
||||
logger.debug('DNS resolver: No record.')
|
||||
except dns.resolver.NoNameservers:
|
||||
@@ -1554,12 +1574,13 @@ def update_ssh_keys(hostname, ssh_dir, create_sshfp):
|
||||
continue
|
||||
|
||||
for line in f:
|
||||
line = line[:-1].lstrip()
|
||||
line = line.strip()
|
||||
if not line or line.startswith('#'):
|
||||
continue
|
||||
try:
|
||||
pubkey = SSHPublicKey(line)
|
||||
except (ValueError, UnicodeDecodeError):
|
||||
except (ValueError, UnicodeDecodeError) as e:
|
||||
logger.debug("Decoding line '%s' failed: %s", line, e)
|
||||
continue
|
||||
logger.info("Adding SSH public key from %s", filename)
|
||||
pubkeys.append(pubkey)
|
||||
@@ -1631,8 +1652,7 @@ def cert_summary(msg, certs, indent=' '):
|
||||
|
||||
|
||||
def get_certs_from_ldap(server, base_dn, realm, ca_enabled):
|
||||
ldap_uri = ipaldap.get_ldap_uri(server)
|
||||
conn = ipaldap.LDAPClient(ldap_uri)
|
||||
conn = ipaldap.LDAPClient.from_hostname_plain(server)
|
||||
try:
|
||||
conn.gssapi_bind()
|
||||
certs = certstore.get_ca_certs(conn, base_dn, realm, ca_enabled)
|
||||
@@ -1917,9 +1937,9 @@ def get_ca_certs(fstore, options, server, basedn, realm):
|
||||
if os.path.exists(ca_file):
|
||||
try:
|
||||
os.unlink(ca_file)
|
||||
except OSError as e:
|
||||
except OSError as e2:
|
||||
logger.error(
|
||||
"Failed to remove '%s': %s", ca_file, e)
|
||||
"Failed to remove '%s': %s", ca_file, e2)
|
||||
raise errors.FileError(
|
||||
reason=u"cannot write certificate file '%s': %s" % (
|
||||
ca_file, e)
|
||||
@@ -2056,8 +2076,6 @@ def install_check(options):
|
||||
cli_domain_source = 'Unknown source'
|
||||
cli_server_source = 'Unknown source'
|
||||
|
||||
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
|
||||
|
||||
if not os.getegid() == 0:
|
||||
raise ScriptError(
|
||||
"You must be root to run ipa-client-install.",
|
||||
@@ -2065,7 +2083,7 @@ def install_check(options):
|
||||
|
||||
tasks.check_selinux_status()
|
||||
|
||||
if is_ipa_client_installed(fstore, on_master=options.on_master):
|
||||
if is_ipa_client_configured(on_master=options.on_master):
|
||||
logger.error("IPA client is already configured on this system.")
|
||||
logger.info(
|
||||
"If you want to reinstall the IPA client, uninstall it first "
|
||||
@@ -2078,10 +2096,13 @@ def install_check(options):
|
||||
try:
|
||||
timeconf.check_timedate_services()
|
||||
except timeconf.NTPConflictingService as e:
|
||||
print("WARNING: conflicting time&date synchronization service '{}'"
|
||||
" will be disabled".format(e.conflicting_service))
|
||||
print("in favor of chronyd")
|
||||
print("")
|
||||
print(
|
||||
"WARNING: conflicting time&date synchronization service "
|
||||
"'{}' will be disabled in favor of chronyd\n".format(
|
||||
e.conflicting_service
|
||||
)
|
||||
)
|
||||
|
||||
except timeconf.NTPConfigurationError:
|
||||
pass
|
||||
|
||||
@@ -2113,6 +2134,13 @@ def install_check(options):
|
||||
"Invalid hostname, '{}' must not be used.".format(hostname),
|
||||
rval=CLIENT_INSTALL_ERROR)
|
||||
|
||||
try:
|
||||
validate_hostname(hostname, maxlen=MAXHOSTNAMELEN)
|
||||
except ValueError as e:
|
||||
raise ScriptError(
|
||||
'invalid hostname: {}'.format(e),
|
||||
rval=CLIENT_INSTALL_ERROR)
|
||||
|
||||
# --no-sssd is not supported any more for rhel-based distros
|
||||
if not tasks.is_nosssd_supported() and not options.sssd:
|
||||
raise ScriptError(
|
||||
@@ -2129,6 +2157,14 @@ def install_check(options):
|
||||
"authentication resources",
|
||||
rval=CLIENT_INSTALL_ERROR)
|
||||
|
||||
# --mkhomedir is not supported by fedora_container and rhel_container
|
||||
if not tasks.is_mkhomedir_supported() and options.mkhomedir:
|
||||
raise ScriptError(
|
||||
"Option '--mkhomedir' is incompatible with the 'authselect' tool "
|
||||
"provided by this distribution for configuring system "
|
||||
"authentication resources",
|
||||
rval=CLIENT_INSTALL_ERROR)
|
||||
|
||||
# when installing with '--no-sssd' option, check whether nss-ldap is
|
||||
# installed
|
||||
if not options.sssd:
|
||||
@@ -2174,7 +2210,7 @@ def install_check(options):
|
||||
raise ScriptError(rval=CLIENT_INSTALL_ERROR)
|
||||
|
||||
# Create the discovery instance
|
||||
ds = ipadiscovery.IPADiscovery()
|
||||
ds = discovery.IPADiscovery()
|
||||
|
||||
ret = ds.search(
|
||||
domain=options.domain,
|
||||
@@ -2197,22 +2233,22 @@ def install_check(options):
|
||||
print_port_conf_info()
|
||||
raise ScriptError(rval=CLIENT_INSTALL_ERROR)
|
||||
|
||||
if ret == ipadiscovery.BAD_HOST_CONFIG:
|
||||
if ret == discovery.BAD_HOST_CONFIG:
|
||||
logger.error("Can't get the fully qualified name of this host")
|
||||
logger.info("Check that the client is properly configured")
|
||||
raise ScriptError(rval=CLIENT_INSTALL_ERROR)
|
||||
if ret == ipadiscovery.NOT_FQDN:
|
||||
if ret == discovery.NOT_FQDN:
|
||||
raise ScriptError(
|
||||
"{} is not a fully-qualified hostname".format(hostname),
|
||||
rval=CLIENT_INSTALL_ERROR)
|
||||
if ret in (ipadiscovery.NO_LDAP_SERVER, ipadiscovery.NOT_IPA_SERVER) \
|
||||
if ret in (discovery.NO_LDAP_SERVER, discovery.NOT_IPA_SERVER) \
|
||||
or not ds.domain:
|
||||
if ret == ipadiscovery.NO_LDAP_SERVER:
|
||||
if ret == discovery.NO_LDAP_SERVER:
|
||||
if ds.server:
|
||||
logger.debug("%s is not an LDAP server", ds.server)
|
||||
else:
|
||||
logger.debug("No LDAP server found")
|
||||
elif ret == ipadiscovery.NOT_IPA_SERVER:
|
||||
elif ret == discovery.NOT_IPA_SERVER:
|
||||
if ds.server:
|
||||
logger.debug("%s is not an IPA server", ds.server)
|
||||
else:
|
||||
@@ -2249,7 +2285,7 @@ def install_check(options):
|
||||
|
||||
client_domain = hostname[hostname.find(".")+1:]
|
||||
|
||||
if ret in (ipadiscovery.NO_LDAP_SERVER, ipadiscovery.NOT_IPA_SERVER) \
|
||||
if ret in (discovery.NO_LDAP_SERVER, discovery.NOT_IPA_SERVER) \
|
||||
or not ds.server:
|
||||
logger.debug("IPA Server not found")
|
||||
if options.server:
|
||||
@@ -2301,13 +2337,13 @@ def install_check(options):
|
||||
cli_server_source = ds.server_source
|
||||
logger.debug("will use discovered server: %s", cli_server[0])
|
||||
|
||||
if ret == ipadiscovery.NOT_IPA_SERVER:
|
||||
if ret == discovery.NOT_IPA_SERVER:
|
||||
logger.error("%s is not an IPA v2 Server.", cli_server[0])
|
||||
print_port_conf_info()
|
||||
logger.debug("(%s: %s)", cli_server[0], cli_server_source)
|
||||
raise ScriptError(rval=CLIENT_INSTALL_ERROR)
|
||||
|
||||
if ret == ipadiscovery.NO_ACCESS_TO_LDAP:
|
||||
if ret == discovery.NO_ACCESS_TO_LDAP:
|
||||
logger.warning("Anonymous access to the LDAP server is disabled.")
|
||||
logger.info("Proceeding without strict verification.")
|
||||
logger.info(
|
||||
@@ -2315,7 +2351,7 @@ def install_check(options):
|
||||
"has been explicitly restricted.")
|
||||
ret = 0
|
||||
|
||||
if ret == ipadiscovery.NO_TLS_LDAP:
|
||||
if ret == discovery.NO_TLS_LDAP:
|
||||
logger.warning(
|
||||
"The LDAP server requires TLS is but we do not have the CA.")
|
||||
logger.info("Proceeding without strict verification.")
|
||||
@@ -2360,6 +2396,11 @@ def install_check(options):
|
||||
"Proceed with fixed values and no DNS discovery?", False):
|
||||
raise ScriptError(rval=CLIENT_INSTALL_ERROR)
|
||||
|
||||
if options.conf_ntp:
|
||||
if not options.on_master and not options.unattended and not (
|
||||
options.ntp_servers or options.ntp_pool):
|
||||
options.ntp_servers, options.ntp_pool = timeconf.get_time_source()
|
||||
|
||||
cli_realm = ds.realm
|
||||
cli_realm_source = ds.realm_source
|
||||
logger.debug("will use discovered realm: %s", cli_realm)
|
||||
@@ -2387,6 +2428,14 @@ def install_check(options):
|
||||
logger.info("BaseDN: %s", cli_basedn)
|
||||
logger.debug("BaseDN source: %s", cli_basedn_source)
|
||||
|
||||
if not options.on_master:
|
||||
if options.ntp_servers:
|
||||
for server in options.ntp_servers:
|
||||
logger.info("NTP server: %s", server)
|
||||
|
||||
if options.ntp_pool:
|
||||
logger.info("NTP pool: %s", options.ntp_pool)
|
||||
|
||||
# ipa-join would fail with IP address instead of a FQDN
|
||||
for srv in cli_server:
|
||||
try:
|
||||
@@ -2452,7 +2501,7 @@ def update_ipa_nssdb():
|
||||
(nickname, sys_db.secdir, e))
|
||||
|
||||
|
||||
def sync_time(options, fstore, statestore):
|
||||
def sync_time(ntp_servers, ntp_pool, fstore, statestore):
|
||||
"""
|
||||
Will disable any other time synchronization service and configure chrony
|
||||
with given ntp(chrony) server and/or pool using Augeas.
|
||||
@@ -2464,18 +2513,24 @@ def sync_time(options, fstore, statestore):
|
||||
# disable other time&date services first
|
||||
timeconf.force_chrony(statestore)
|
||||
|
||||
if not ntp_servers and not ntp_pool:
|
||||
# autodiscovery happens in case that NTP configuration isn't explicitly
|
||||
# disabled and user did not provide any NTP server addresses or
|
||||
# NTP pool address to the installer interactively or as an cli argument
|
||||
ds = discovery.IPADiscovery()
|
||||
ntp_servers = ds.ipadns_search_srv(
|
||||
cli_domain, '_ntp._udp', None, break_on_first=False
|
||||
)
|
||||
if ntp_servers:
|
||||
for server in ntp_servers:
|
||||
# when autodiscovery found server records
|
||||
logger.debug("Found DNS record for NTP server: \t%s", server)
|
||||
|
||||
logger.info('Synchronizing time')
|
||||
|
||||
if not options.ntp_servers:
|
||||
ds = ipadiscovery.IPADiscovery()
|
||||
ntp_servers = ds.ipadns_search_srv(cli_domain, '_ntp._udp',
|
||||
None, break_on_first=False)
|
||||
else:
|
||||
ntp_servers = options.ntp_servers
|
||||
|
||||
configured = False
|
||||
if ntp_servers or options.ntp_pool:
|
||||
configured = timeconf.configure_chrony(ntp_servers, options.ntp_pool,
|
||||
if ntp_servers or ntp_pool:
|
||||
configured = timeconf.configure_chrony(ntp_servers, ntp_pool,
|
||||
fstore, statestore)
|
||||
else:
|
||||
logger.warning("No SRV records of NTP servers found and no NTP server "
|
||||
@@ -2548,6 +2603,8 @@ def _install(options):
|
||||
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
|
||||
statestore = sysrestore.StateFile(paths.IPA_CLIENT_SYSRESTORE)
|
||||
|
||||
statestore.backup_state('installation', 'complete', False)
|
||||
|
||||
if not options.on_master:
|
||||
# Try removing old principals from the keytab
|
||||
purge_host_keytab(cli_realm)
|
||||
@@ -2560,7 +2617,7 @@ def _install(options):
|
||||
|
||||
if options.conf_ntp:
|
||||
# Attempt to configure and sync time with NTP server (chrony).
|
||||
sync_time(options, fstore, statestore)
|
||||
sync_time(options.ntp_servers, options.ntp_pool, fstore, statestore)
|
||||
elif options.on_master:
|
||||
# If we're on master skipping the time sync here because it was done
|
||||
# in ipa-server-install
|
||||
@@ -2598,10 +2655,13 @@ def _install(options):
|
||||
force=options.force)
|
||||
env['KRB5_CONFIG'] = krb_name
|
||||
ccache_name = os.path.join(ccache_dir, 'ccache')
|
||||
join_args = [paths.SBIN_IPA_JOIN,
|
||||
"-s", cli_server[0],
|
||||
"-b", str(realm_to_suffix(cli_realm)),
|
||||
"-h", hostname]
|
||||
join_args = [
|
||||
paths.SBIN_IPA_JOIN,
|
||||
"-s", cli_server[0],
|
||||
"-b", str(realm_to_suffix(cli_realm)),
|
||||
"-h", hostname,
|
||||
"-k", paths.KRB5_KEYTAB
|
||||
]
|
||||
if options.debug:
|
||||
join_args.append("-d")
|
||||
env['XMLRPC_TRACE_CURL'] = 'yes'
|
||||
@@ -3131,19 +3191,22 @@ def _install(options):
|
||||
configure_nisdomain(
|
||||
options=options, domain=cli_domain, statestore=statestore)
|
||||
|
||||
statestore.delete_state('installation', 'complete')
|
||||
statestore.backup_state('installation', 'complete', True)
|
||||
logger.info('Client configuration complete.')
|
||||
|
||||
|
||||
def uninstall_check(options):
|
||||
fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE)
|
||||
|
||||
if not is_ipa_client_installed(fstore):
|
||||
if not is_ipa_client_configured():
|
||||
if options.on_master:
|
||||
rval = SUCCESS
|
||||
else:
|
||||
rval = CLIENT_NOT_CONFIGURED
|
||||
raise ScriptError(
|
||||
"IPA client is not configured on this system.",
|
||||
rval=CLIENT_NOT_CONFIGURED)
|
||||
rval=rval)
|
||||
|
||||
server_fstore = sysrestore.FileStore(paths.SYSRESTORE)
|
||||
if server_fstore.has_files() and not options.on_master:
|
||||
if is_ipa_configured() and not options.on_master:
|
||||
logger.error(
|
||||
"IPA client is configured as a part of IPA server on this system.")
|
||||
logger.info("Refer to ipa-server-install for uninstallation.")
|
||||
@@ -3250,7 +3313,12 @@ def uninstall(options):
|
||||
|
||||
if not options.on_master and os.path.exists(paths.IPA_DEFAULT_CONF):
|
||||
logger.info("Unenrolling client from IPA server")
|
||||
join_args = [paths.SBIN_IPA_JOIN, "--unenroll", "-h", hostname]
|
||||
join_args = [
|
||||
paths.SBIN_IPA_JOIN,
|
||||
"--unenroll",
|
||||
"-h", hostname,
|
||||
"-k", paths.KRB5_KEYTAB
|
||||
]
|
||||
if options.debug:
|
||||
join_args.append("-d")
|
||||
env['XMLRPC_TRACE_CURL'] = 'yes'
|
||||
@@ -3431,6 +3499,7 @@ def uninstall(options):
|
||||
restore_time_sync(statestore, fstore)
|
||||
|
||||
if was_sshd_configured and services.knownservices.sshd.is_running():
|
||||
remove_file(paths.SSHD_IPA_CONFIG)
|
||||
services.knownservices.sshd.restart()
|
||||
|
||||
# Remove the Firefox configuration
|
||||
@@ -3454,6 +3523,8 @@ def uninstall(options):
|
||||
if fstore.has_files():
|
||||
logger.error('Some files have not been restored, see %s',
|
||||
paths.SYSRESTORE_INDEX)
|
||||
|
||||
statestore.delete_state('installation', 'complete')
|
||||
has_state = False
|
||||
for module in statestore.modules:
|
||||
logger.error(
|
||||
@@ -3682,6 +3753,7 @@ class ClientInstallInterface(hostname_.HostNameInstallInterface,
|
||||
|
||||
request_cert = knob(
|
||||
None,
|
||||
deprecated=True,
|
||||
description="request certificate for the machine",
|
||||
)
|
||||
request_cert = prepare_only(request_cert)
|
||||
@@ -3694,7 +3766,10 @@ class ClientInstallInterface(hostname_.HostNameInstallInterface,
|
||||
"--server cannot be used without providing --domain")
|
||||
|
||||
if self.force_ntpd:
|
||||
logger.warning("Option --force-ntpd has been deprecated")
|
||||
logger.warning(
|
||||
"Option --force-ntpd has been deprecated and will be "
|
||||
"removed in a future release."
|
||||
)
|
||||
|
||||
if self.ntp_servers and self.no_ntp:
|
||||
raise RuntimeError(
|
||||
@@ -3704,6 +3779,12 @@ class ClientInstallInterface(hostname_.HostNameInstallInterface,
|
||||
raise RuntimeError(
|
||||
"--ntp-pool cannot be used together with --no-ntp")
|
||||
|
||||
if self.request_cert:
|
||||
logger.warning(
|
||||
"Option --request-cert has been deprecated and will be "
|
||||
"removed in a future release."
|
||||
)
|
||||
|
||||
if self.no_nisdomain and self.nisdomain:
|
||||
raise RuntimeError(
|
||||
"--no-nisdomain cannot be used together with --nisdomain")
|
||||
|
||||
Reference in New Issue
Block a user